hiding variable-length fields from Form_pg_* structs
It would be helpful if variable length catalog fields (except the first
one) would not be visible on the C level in the Form_pg_* structs. We
keep them listed in the include/catalog/pg_*.h files so that the BKI
generating code can see them and for general documentation, but the
fields are meaningless in C, and some catalog files contain free-form
comments advising the reader of that. If we could hide them somehow, we
would avoid random programming bugs, deconfuse compilers trying to
generate useful warnings, and save occasional stack space. There are
several known cases of the first and second issue, at least.
I haven't found the ideal way to implement that yet, but the general
idea would be something like:
CATALOG(pg_attribute,1249) BKI_BOOTSTRAP ...
{
...
int4 attinhcount;
Oid attcollation;
aclitem attacl[1];
CATVARLEN(
text attoptions[1];
text attfdwoptions[1];
)
} FormData_pg_attribute;
where CATVARLEN is defined empty in C, and ignored in the BKI generation
code.
The real trick is to find something that handles well with pgindent and
indenting text editors.
Ideas?
Peter Eisentraut <peter_e@gmx.net> writes:
CATALOG(pg_attribute,1249) BKI_BOOTSTRAP ...
{
...
int4 attinhcount;
Oid attcollation;
aclitem attacl[1];
CATVARLEN(
text attoptions[1];
text attfdwoptions[1];
)
} FormData_pg_attribute;
where CATVARLEN is defined empty in C, and ignored in the BKI generation
code.
The real trick is to find something that handles well with pgindent and
indenting text editors.
The low-tech way would be
CATALOG(pg_attribute,1249) BKI_BOOTSTRAP ...
{
...
int4 attinhcount;
Oid attcollation;
aclitem attacl[1];
#ifdef CATALOG_VARLEN_FIELDS
text attoptions[1];
text attfdwoptions[1];
#endif
} FormData_pg_attribute;
regards, tom lane
On sön, 2011-11-27 at 18:20 -0500, Tom Lane wrote:
The low-tech way would be
CATALOG(pg_attribute,1249) BKI_BOOTSTRAP ...
{
...
int4 attinhcount;
Oid attcollation;
aclitem attacl[1];
#ifdef CATALOG_VARLEN_FIELDS
text attoptions[1];
text attfdwoptions[1];
#endif
} FormData_pg_attribute;
Good enough.
To clarify, I believe the rule is that the first variable-length field
can be accessed as a struct field. Are there any exceptions to this?
This kind of comment is pretty confusing:
CATALOG(pg_rewrite,2618)
{
NameData rulename;
Oid ev_class;
int2 ev_attr;
char ev_type;
char ev_enabled;
bool is_instead;
/* NB: remaining fields must be accessed via heap_getattr */
pg_node_tree ev_qual;
pg_node_tree ev_action;
} FormData_pg_rewrite;
Also, this code in relcache.c accesses indclass, which is after an
int2vector and an oidvector field:
/* Check to see if it is a unique, non-partial btree index on OID */
if (index->indnatts == 1 &&
index->indisunique && index->indimmediate &&
index->indkey.values[0] == ObjectIdAttributeNumber &&
index->indclass.values[0] == OID_BTREE_OPS_OID &&
heap_attisnull(htup, Anum_pg_index_indpred))
oidIndex = index->indexrelid;
Peter Eisentraut <peter_e@gmx.net> writes:
To clarify, I believe the rule is that the first variable-length field
can be accessed as a struct field. Are there any exceptions to this?
If it is known not null, yes, but I wonder just how many places actually
depend on that. It might be better to remove all varlena fields from C
visibility and require use of the accessor functions. We should at
least look into what that would cost us.
Also, this code in relcache.c accesses indclass, which is after an
int2vector and an oidvector field:
/* Check to see if it is a unique, non-partial btree index on OID */
if (index->indnatts == 1 &&
index->indisunique && index->indimmediate &&
index->indkey.values[0] == ObjectIdAttributeNumber &&
index->indclass.values[0] == OID_BTREE_OPS_OID &&
heap_attisnull(htup, Anum_pg_index_indpred))
oidIndex = index->indexrelid;
Hmm, that does look mighty broken, doesn't it ... but somehow it works,
else GetNewOid would be bleating all the time. (Thinks about that for
a bit) Oh, it accidentally fails to fail because the C declarations
for int2vector and oidvector are actually correct if there is a single
element in the arrays, which we already verified with the indnatts test.
But yeah, this seems horribly fragile, and it should not be performance
critical because we only go through here when loading up a cache entry.
So let's change it.
regards, tom lane
On Mon, Dec 5, 2011 at 2:47 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Peter Eisentraut <peter_e@gmx.net> writes:
To clarify, I believe the rule is that the first variable-length field
can be accessed as a struct field. Are there any exceptions to this?If it is known not null, yes, but I wonder just how many places actually
depend on that. It might be better to remove all varlena fields from C
visibility and require use of the accessor functions. We should at
least look into what that would cost us.
My impression is that all the varlena fields also allow nulls. So I
think there's no point in trying to keep the first one C-accessible.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
Robert Haas <robertmhaas@gmail.com> writes:
On Mon, Dec 5, 2011 at 2:47 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Peter Eisentraut <peter_e@gmx.net> writes:
To clarify, I believe the rule is that the first variable-length field
can be accessed as a struct field. Are there any exceptions to this?
If it is known not null, yes, but I wonder just how many places actually
depend on that.
My impression is that all the varlena fields also allow nulls.
See MARKNOTNULL in bootstrap.c. I think the exceptions were designed to
protect direct accesses to pg_index.
regards, tom lane
On Mon, Dec 5, 2011 at 3:12 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Robert Haas <robertmhaas@gmail.com> writes:
On Mon, Dec 5, 2011 at 2:47 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Peter Eisentraut <peter_e@gmx.net> writes:
To clarify, I believe the rule is that the first variable-length field
can be accessed as a struct field. Are there any exceptions to this?If it is known not null, yes, but I wonder just how many places actually
depend on that.My impression is that all the varlena fields also allow nulls.
See MARKNOTNULL in bootstrap.c. I think the exceptions were designed to
protect direct accesses to pg_index.
Hmm, OK.
rhaas=# select r.relname, a.attname, a.atttypid::regtype from pg_class
r, pg_attribute a where relnamespace=11 and relkind='r' and attrelid =
r.oid and a.attnotnull and a.attlen<0;
relname | attname | atttypid
------------+--------------+------------
pg_proc | proargtypes | oidvector
pg_index | indkey | int2vector
pg_index | indcollation | oidvector
pg_index | indclass | oidvector
pg_index | indoption | int2vector
pg_trigger | tgattr | int2vector
(6 rows)
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
So here is a patch for that.
There are a few cases that break when hiding all variable length fields:
Access to indclass in relcache.c, as discussed upthread, which should be
fixed.
Access to pg_largeobject.data. This is apparently OK, per comment in
inv_api.c.
Access to pg_proc.proargtypes in various places. This is clearly
useful, so we'll keep it visible.
So I think the relcache.c thing should be fixed and then this might be
good to go.
Attachments:
catalog-varlen.patchtext/x-patch; charset=UTF-8; name=catalog-varlen.patchDownload
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index 1ba935c..1b8db1b 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -143,6 +143,7 @@ sub Catalogs
elsif ($declaring_attributes)
{
next if (/^{|^$/);
+ next if (/^#/);
if (/^}/)
{
undef $declaring_attributes;
@@ -150,6 +151,7 @@ sub Catalogs
else
{
my ($atttype, $attname) = split /\s+/, $_;
+ die unless $attname;
if (exists $RENAME_ATTTYPE{$atttype})
{
$atttype = $RENAME_ATTTYPE{$atttype};
diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index 5fe3a5b..bcf31e6 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -22,6 +22,16 @@
/* Introduces a catalog's structure definition */
#define CATALOG(name,oid) typedef struct CppConcat(FormData_,name)
+/*
+ * This is never defined; it's here only for documentation.
+ *
+ * Variable-length catalog fields (except possibly the first not nullable one)
+ * should not be visible in C structures, so they are made invisible by #ifdefs
+ * of an undefined symbol. See also MARKNOTNULL in bootstrap.c for how this is
+ * handled.
+ */
+#undef CATALOG_VARLEN
+
/* Options that may appear after CATALOG (on the same line) */
#define BKI_BOOTSTRAP
#define BKI_SHARED_RELATION
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 4e10021..c420bdb 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -44,7 +44,9 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS
regproc aggfinalfn;
Oid aggsortop;
Oid aggtranstype;
+#ifdef CATALOG_VARLEN
text agginitval; /* VARIABLE LENGTH FIELD */
+#endif
} FormData_pg_aggregate;
/* ----------------
diff --git a/src/include/catalog/pg_attrdef.h b/src/include/catalog/pg_attrdef.h
index 01f663c..ee205ec 100644
--- a/src/include/catalog/pg_attrdef.h
+++ b/src/include/catalog/pg_attrdef.h
@@ -32,8 +32,10 @@ CATALOG(pg_attrdef,2604)
{
Oid adrelid; /* OID of table containing attribute */
int2 adnum; /* attnum of attribute */
+#ifdef CATALOG_VARLEN
pg_node_tree adbin; /* nodeToString representation of default */
text adsrc; /* human-readable representation of default */
+#endif
} FormData_pg_attrdef;
/* ----------------
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index 5cb16f6..7d6d0ac 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -151,6 +151,7 @@ CATALOG(pg_attribute,1249) BKI_BOOTSTRAP BKI_WITHOUT_OIDS BKI_ROWTYPE_OID(75) BK
* NOTE: the following fields are not present in tuple descriptors!
*/
+#ifdef CATALOG_VARLEN
/* Column-level access permissions */
aclitem attacl[1];
@@ -159,6 +160,7 @@ CATALOG(pg_attribute,1249) BKI_BOOTSTRAP BKI_WITHOUT_OIDS BKI_ROWTYPE_OID(75) BK
/* Column-level FDW options */
text attfdwoptions[1];
+#endif
} FormData_pg_attribute;
/*
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 829f9b9..97a51d3 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -74,8 +74,10 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO
* NOTE: these fields are not present in a relcache entry's rd_rel field.
*/
+#ifdef CATALOG_VARLEN
aclitem relacl[1]; /* access permissions */
text reloptions[1]; /* access-method-specific options */
+#endif
} FormData_pg_class;
/* Size of fixed part of pg_class tuples, not counting var-length fields */
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index c962834..91bcc54 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -130,6 +130,7 @@ CATALOG(pg_constraint,2606)
*/
Oid conexclop[1];
+#ifdef CATALOG_VARLEN
/*
* If a check constraint, nodeToString representation of expression
*/
@@ -139,6 +140,7 @@ CATALOG(pg_constraint,2606)
* If a check constraint, source-text representation of expression
*/
text consrc;
+#endif
} FormData_pg_constraint;
/* ----------------
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index 57537c8..3875d3f 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -42,7 +42,9 @@ CATALOG(pg_database,1262) BKI_SHARED_RELATION BKI_ROWTYPE_OID(1248) BKI_SCHEMA_M
Oid datlastsysoid; /* highest OID to consider a system OID */
TransactionId datfrozenxid; /* all Xids < this are frozen in this DB */
Oid dattablespace; /* default table space for this DB */
+#ifdef CATALOG_VARLEN
aclitem datacl[1]; /* access permissions (VAR LENGTH) */
+#endif
} FormData_pg_database;
/* ----------------
diff --git a/src/include/catalog/pg_db_role_setting.h b/src/include/catalog/pg_db_role_setting.h
index 1924043..573f83a 100644
--- a/src/include/catalog/pg_db_role_setting.h
+++ b/src/include/catalog/pg_db_role_setting.h
@@ -35,7 +35,9 @@ CATALOG(pg_db_role_setting,2964) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
{
Oid setdatabase; /* database */
Oid setrole; /* role */
+#ifdef CATALOG_VARLEN
text setconfig[1]; /* GUC settings to apply at login */
+#endif
} FormData_pg_db_role_setting;
typedef FormData_pg_db_role_setting *Form_pg_db_role_setting;
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index 9fd207d..63d9ed8 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -37,7 +37,9 @@ CATALOG(pg_default_acl,826)
* VARIABLE LENGTH FIELDS start here.
*/
+#ifdef CATALOG_VARLEN
aclitem defaclacl[1]; /* permissions to add at CREATE time */
+#endif
} FormData_pg_default_acl;
/* ----------------
diff --git a/src/include/catalog/pg_description.h b/src/include/catalog/pg_description.h
index 0e06500..6947608 100644
--- a/src/include/catalog/pg_description.h
+++ b/src/include/catalog/pg_description.h
@@ -50,7 +50,9 @@ CATALOG(pg_description,2609) BKI_WITHOUT_OIDS
Oid objoid; /* OID of object itself */
Oid classoid; /* OID of table containing object */
int4 objsubid; /* column number, or 0 if not used */
+#ifdef CATALOG_VARLEN
text description; /* description of object */
+#endif
} FormData_pg_description;
/* ----------------
diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h
index 606ed9a..9f25f9c 100644
--- a/src/include/catalog/pg_extension.h
+++ b/src/include/catalog/pg_extension.h
@@ -40,9 +40,11 @@ CATALOG(pg_extension,3079)
*
* extversion should never be null, but the others can be.
*/
+#ifdef CATALOG_VARLEN
text extversion; /* extension version name */
Oid extconfig[1]; /* dumpable configuration tables */
text extcondition[1]; /* WHERE clauses for config tables */
+#endif
} FormData_pg_extension;
/* ----------------
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index 90a51a2..1dfc1b5 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -37,8 +37,10 @@ CATALOG(pg_foreign_data_wrapper,2328)
/* VARIABLE LENGTH FIELDS start here. */
+#ifdef CATALOG_VARLEN
aclitem fdwacl[1]; /* access permissions */
text fdwoptions[1]; /* FDW options */
+#endif
} FormData_pg_foreign_data_wrapper;
/* ----------------
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index a96328c..7a51eee 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -35,10 +35,12 @@ CATALOG(pg_foreign_server,1417)
/*
* VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
*/
+#ifdef CATALOG_VARLEN
text srvtype;
text srvversion;
aclitem srvacl[1]; /* access permissions */
text srvoptions[1]; /* FDW-specific options */
+#endif
} FormData_pg_foreign_server;
/* ----------------
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index 71992d3..7c85b93 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -30,7 +30,9 @@ CATALOG(pg_foreign_table,3118) BKI_WITHOUT_OIDS
{
Oid ftrelid; /* OID of foreign table */
Oid ftserver; /* OID of foreign server */
+#ifdef CATALOG_VARLEN
text ftoptions[1]; /* FDW-specific options */
+#endif
} FormData_pg_foreign_table;
/* ----------------
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index 6c301ff..0546f59 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -47,11 +47,14 @@ CATALOG(pg_index,2610) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO
oidvector indcollation; /* collation identifiers */
oidvector indclass; /* opclass identifiers */
int2vector indoption; /* per-column flags (AM-specific meanings) */
+/*FIXME*/
+#ifdef CATALOG_VARLEN
pg_node_tree indexprs; /* expression trees for index attributes that
* are not simple column references; one for
* each zero entry in indkey[] */
pg_node_tree indpred; /* expression tree for predicate, if a partial
* index; else NULL */
+#endif
} FormData_pg_index;
/* ----------------
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index fd8ea0b..8bd819d 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -37,7 +37,9 @@ CATALOG(pg_language,2612)
Oid lanplcallfoid; /* Call handler for PL */
Oid laninline; /* Optional anonymous-block handler function */
Oid lanvalidator; /* Optional validation function */
+#ifdef CATALOG_VARLEN
aclitem lanacl[1]; /* Access privileges */
+#endif
} FormData_pg_language;
/* ----------------
diff --git a/src/include/catalog/pg_largeobject.h b/src/include/catalog/pg_largeobject.h
index 7c53e1e..0f4965c 100644
--- a/src/include/catalog/pg_largeobject.h
+++ b/src/include/catalog/pg_largeobject.h
@@ -32,7 +32,9 @@ CATALOG(pg_largeobject,2613) BKI_WITHOUT_OIDS
{
Oid loid; /* Identifier of large object */
int4 pageno; /* Page number (starting from 0) */
+/*FIXME: #ifdef CATALOG_VARLEN*/
bytea data; /* Data for page (may be zero-length) */
+/*#endif*/
} FormData_pg_largeobject;
/* ----------------
diff --git a/src/include/catalog/pg_largeobject_metadata.h b/src/include/catalog/pg_largeobject_metadata.h
index dea4d12..7f235ee 100644
--- a/src/include/catalog/pg_largeobject_metadata.h
+++ b/src/include/catalog/pg_largeobject_metadata.h
@@ -31,7 +31,9 @@
CATALOG(pg_largeobject_metadata,2995)
{
Oid lomowner; /* OID of the largeobject owner */
+#ifdef CATALOG_VARLEN
aclitem lomacl[1]; /* access permissions */
+#endif
} FormData_pg_largeobject_metadata;
/* ----------------
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index 52a97f1..07e1b5e 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -37,7 +37,9 @@ CATALOG(pg_namespace,2615)
{
NameData nspname;
Oid nspowner;
+#ifdef CATALOG_VARLEN
aclitem nspacl[1]; /* VARIABLE LENGTH FIELD */
+#endif
} FormData_pg_namespace;
/* ----------------
diff --git a/src/include/catalog/pg_pltemplate.h b/src/include/catalog/pg_pltemplate.h
index ce249c0..29f356f 100644
--- a/src/include/catalog/pg_pltemplate.h
+++ b/src/include/catalog/pg_pltemplate.h
@@ -33,11 +33,13 @@ CATALOG(pg_pltemplate,1136) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
NameData tmplname; /* name of PL */
bool tmpltrusted; /* PL is trusted? */
bool tmpldbacreate; /* PL is installable by db owner? */
+#ifdef CATALOG_VARLEN
text tmplhandler; /* name of call handler function */
text tmplinline; /* name of anonymous-block handler, or NULL */
text tmplvalidator; /* name of validator function, or NULL */
text tmpllibrary; /* path of shared library */
aclitem tmplacl[1]; /* access privileges for template */
+#endif
} FormData_pg_pltemplate;
/* ----------------
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 355c61a..0a18685 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -55,6 +55,7 @@ CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO
/* VARIABLE LENGTH FIELDS: */
oidvector proargtypes; /* parameter types (excludes OUT params) */
+#ifdef CATALOG_VARLEN
Oid proallargtypes[1]; /* all param types (NULL if IN only) */
char proargmodes[1]; /* parameter modes (NULL if IN only) */
text proargnames[1]; /* parameter names (NULL if no names) */
@@ -64,6 +65,7 @@ CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO
text probin; /* secondary procedure info (can be NULL) */
text proconfig[1]; /* procedure-local GUC settings */
aclitem proacl[1]; /* access permissions */
+#endif
} FormData_pg_proc;
/* ----------------
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index eb16b2d..997e0c3 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -41,8 +41,10 @@ CATALOG(pg_rewrite,2618)
bool is_instead;
/* NB: remaining fields must be accessed via heap_getattr */
+#ifdef CATALOG_VARLEN
pg_node_tree ev_qual;
pg_node_tree ev_action;
+#endif
} FormData_pg_rewrite;
/* ----------------
diff --git a/src/include/catalog/pg_seclabel.h b/src/include/catalog/pg_seclabel.h
index b468d69..fa9b1e1 100644
--- a/src/include/catalog/pg_seclabel.h
+++ b/src/include/catalog/pg_seclabel.h
@@ -25,8 +25,10 @@ CATALOG(pg_seclabel,3596) BKI_WITHOUT_OIDS
Oid objoid; /* OID of the object itself */
Oid classoid; /* OID of table containing the object */
int4 objsubid; /* column number, or 0 if not used */
+#ifdef CATALOG_VARLEN
text provider; /* name of label provider */
text label; /* security label of the object */
+#endif
} FormData_pg_seclabel;
/* ----------------
diff --git a/src/include/catalog/pg_shdescription.h b/src/include/catalog/pg_shdescription.h
index 6d0ee3b..c0f12e6 100644
--- a/src/include/catalog/pg_shdescription.h
+++ b/src/include/catalog/pg_shdescription.h
@@ -42,7 +42,9 @@ CATALOG(pg_shdescription,2396) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
{
Oid objoid; /* OID of object itself */
Oid classoid; /* OID of table containing object */
+#ifdef CATALOG_VARLEN
text description; /* description of object */
+#endif
} FormData_pg_shdescription;
/* ----------------
diff --git a/src/include/catalog/pg_shseclabel.h b/src/include/catalog/pg_shseclabel.h
index 235564f..0f10faf 100644
--- a/src/include/catalog/pg_shseclabel.h
+++ b/src/include/catalog/pg_shseclabel.h
@@ -24,8 +24,10 @@ CATALOG(pg_shseclabel,3592) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
{
Oid objoid; /* OID of the shared object itself */
Oid classoid; /* OID of table containing the shared object */
+#ifdef CATALOG_VARLEN
text provider; /* name of label provider */
text label; /* security label of the object */
+#endif
} FormData_pg_shseclabel;
/* ----------------
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 7d1d127..4625eab 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -121,10 +121,12 @@ CATALOG(pg_statistic,2619) BKI_WITHOUT_OIDS
* presently have to cheat quite a bit to allow polymorphic arrays of this
* kind, but perhaps someday it'll be a less bogus facility.
*/
+#ifdef CATALOG_VARLEN
anyarray stavalues1;
anyarray stavalues2;
anyarray stavalues3;
anyarray stavalues4;
+#endif
} FormData_pg_statistic;
#define STATISTIC_NUM_SLOTS 4
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index a6a0686..399bb64 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -32,8 +32,10 @@ CATALOG(pg_tablespace,1213) BKI_SHARED_RELATION
{
NameData spcname; /* tablespace name */
Oid spcowner; /* owner of tablespace */
+#ifdef CATALOG_VARLEN
aclitem spcacl[1]; /* access permissions (VAR LENGTH) */
text spcoptions[1]; /* per-tablespace options */
+#endif
} FormData_pg_tablespace;
/* ----------------
diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h
index 1f29d21..7e5d9d0 100644
--- a/src/include/catalog/pg_trigger.h
+++ b/src/include/catalog/pg_trigger.h
@@ -52,8 +52,10 @@ CATALOG(pg_trigger,2620)
/* VARIABLE LENGTH FIELDS (note: tgattr and tgargs must not be null) */
int2vector tgattr; /* column numbers, if trigger is on columns */
+#ifdef CATALOG_VARLEN
bytea tgargs; /* first\000second\000tgnargs\000 */
pg_node_tree tgqual; /* WHEN expression, or NULL if none */
+#endif
} FormData_pg_trigger;
/* ----------------
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
index 5036b8c..86e33e8 100644
--- a/src/include/catalog/pg_ts_dict.h
+++ b/src/include/catalog/pg_ts_dict.h
@@ -36,7 +36,9 @@ CATALOG(pg_ts_dict,3600)
Oid dictnamespace; /* name space */
Oid dictowner; /* owner */
Oid dicttemplate; /* dictionary's template */
+#ifdef CATALOG_VARLEN
text dictinitoption; /* options passed to dict_init() */
+#endif
} FormData_pg_ts_dict;
typedef FormData_pg_ts_dict *Form_pg_ts_dict;
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index e12efe4..b7fea03 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -200,6 +200,7 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
*/
Oid typcollation;
+#ifdef CATALOG_VARLEN
/*
* If typdefaultbin is not NULL, it is the nodeToString representation of
* a default expression for the type. Currently this is only used for
@@ -221,6 +222,7 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
* Access permissions
*/
aclitem typacl[1]; /* VARIABLE LENGTH FIELD */
+#endif
} FormData_pg_type;
/* ----------------
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index 551000f..76d7422 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -36,7 +36,9 @@ CATALOG(pg_user_mapping,1418)
* VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
*/
+#ifdef CATALOG_VARLEN
text umoptions[1]; /* user mapping options */
+#endif
} FormData_pg_user_mapping;
/* ----------------
Peter Eisentraut <peter_e@gmx.net> writes:
So I think the relcache.c thing should be fixed and then this might be
good to go.
Cosmetic gripes: I think we could get rid of the various comments that
say things like "variable length fields start here", since the #ifdef
CATALOG_VARLEN lines now represent that in a standardized fashion.
Possibly those lines should be
#ifdef CATALOG_VARLEN /* variable-length fields start here */
to be even clearer.
What would be appropriate to add instead of those inconsistently-used
comments is explicit comments about the exception cases such as
proargtypes, to make it clear that the placement of the #ifdef
CATALOG_VARLEN is intentional and not a bug in those cases.
regards, tom lane
On mån, 2012-01-09 at 14:04 -0500, Tom Lane wrote:
#ifdef CATALOG_VARLEN /* variable-length fields start here
*/to be even clearer.
What would be appropriate to add instead of those inconsistently-used
comments is explicit comments about the exception cases such as
proargtypes, to make it clear that the placement of the #ifdef
CATALOG_VARLEN is intentional and not a bug in those cases.
I implemented your suggestions in the attached patch.
Attachments:
catalog-varlen.patchtext/x-patch; charset=UTF-8; name=catalog-varlen.patchDownload
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index 1ba935c..cdb0bee 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -143,6 +143,7 @@ sub Catalogs
elsif ($declaring_attributes)
{
next if (/^{|^$/);
+ next if (/^#/);
if (/^}/)
{
undef $declaring_attributes;
@@ -150,6 +151,7 @@ sub Catalogs
else
{
my ($atttype, $attname) = split /\s+/, $_;
+ die "parse error ($input_file)" unless $attname;
if (exists $RENAME_ATTTYPE{$atttype})
{
$atttype = $RENAME_ATTTYPE{$atttype};
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index d0138fc..a59950e 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -3351,15 +3351,30 @@ RelationGetIndexList(Relation relation)
while (HeapTupleIsValid(htup = systable_getnext(indscan)))
{
Form_pg_index index = (Form_pg_index) GETSTRUCT(htup);
+ Datum indclassDatum;
+ oidvector *indclass;
+ bool isnull;
/* Add index's OID to result list in the proper order */
result = insert_ordered_oid(result, index->indexrelid);
+ /*
+ * indclass cannot be referenced directly through the C struct, because
+ * it comes after the variable-width indkey field. Must extract the
+ * datum the hard way...
+ */
+ indclassDatum = heap_getattr(htup,
+ Anum_pg_index_indclass,
+ GetPgIndexDescriptor(),
+ &isnull);
+ Assert(!isnull);
+ indclass = (oidvector *) DatumGetPointer(indclassDatum);
+
/* Check to see if it is a unique, non-partial btree index on OID */
if (index->indnatts == 1 &&
index->indisunique && index->indimmediate &&
index->indkey.values[0] == ObjectIdAttributeNumber &&
- index->indclass.values[0] == OID_BTREE_OPS_OID &&
+ indclass->values[0] == OID_BTREE_OPS_OID &&
heap_attisnull(htup, Anum_pg_index_indpred))
oidIndex = index->indexrelid;
}
diff --git a/src/include/catalog/genbki.h b/src/include/catalog/genbki.h
index 5fe3a5b..bcf31e6 100644
--- a/src/include/catalog/genbki.h
+++ b/src/include/catalog/genbki.h
@@ -22,6 +22,16 @@
/* Introduces a catalog's structure definition */
#define CATALOG(name,oid) typedef struct CppConcat(FormData_,name)
+/*
+ * This is never defined; it's here only for documentation.
+ *
+ * Variable-length catalog fields (except possibly the first not nullable one)
+ * should not be visible in C structures, so they are made invisible by #ifdefs
+ * of an undefined symbol. See also MARKNOTNULL in bootstrap.c for how this is
+ * handled.
+ */
+#undef CATALOG_VARLEN
+
/* Options that may appear after CATALOG (on the same line) */
#define BKI_BOOTSTRAP
#define BKI_SHARED_RELATION
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index 4e10021..0c8a20c 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -44,7 +44,9 @@ CATALOG(pg_aggregate,2600) BKI_WITHOUT_OIDS
regproc aggfinalfn;
Oid aggsortop;
Oid aggtranstype;
- text agginitval; /* VARIABLE LENGTH FIELD */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ text agginitval;
+#endif
} FormData_pg_aggregate;
/* ----------------
diff --git a/src/include/catalog/pg_attrdef.h b/src/include/catalog/pg_attrdef.h
index 01f663c..ad770e4 100644
--- a/src/include/catalog/pg_attrdef.h
+++ b/src/include/catalog/pg_attrdef.h
@@ -32,8 +32,10 @@ CATALOG(pg_attrdef,2604)
{
Oid adrelid; /* OID of table containing attribute */
int2 adnum; /* attnum of attribute */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
pg_node_tree adbin; /* nodeToString representation of default */
text adsrc; /* human-readable representation of default */
+#endif
} FormData_pg_attrdef;
/* ----------------
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index 5cb16f6..45e38e4 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -145,11 +145,8 @@ CATALOG(pg_attribute,1249) BKI_BOOTSTRAP BKI_WITHOUT_OIDS BKI_ROWTYPE_OID(75) BK
/* attribute's collation */
Oid attcollation;
- /*
- * VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
- *
- * NOTE: the following fields are not present in tuple descriptors!
- */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ /* NOTE: The following fields are not present in tuple descriptors. */
/* Column-level access permissions */
aclitem attacl[1];
@@ -159,6 +156,7 @@ CATALOG(pg_attribute,1249) BKI_BOOTSTRAP BKI_WITHOUT_OIDS BKI_ROWTYPE_OID(75) BK
/* Column-level FDW options */
text attfdwoptions[1];
+#endif
} FormData_pg_attribute;
/*
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 829f9b9..3b01bb4 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -68,14 +68,11 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO
bool relhassubclass; /* has (or has had) derived classes */
TransactionId relfrozenxid; /* all Xids < this are frozen in this rel */
- /*
- * VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
- *
- * NOTE: these fields are not present in a relcache entry's rd_rel field.
- */
-
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ /* NOTE: These fields are not present in a relcache entry's rd_rel field. */
aclitem relacl[1]; /* access permissions */
text reloptions[1]; /* access-method-specific options */
+#endif
} FormData_pg_class;
/* Size of fixed part of pg_class tuples, not counting var-length fields */
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index c962834..77015ae 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -91,10 +91,7 @@ CATALOG(pg_constraint,2606)
/* Has a local definition and cannot be inherited */
bool conisonly;
- /*
- * VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
- */
-
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
/*
* Columns of conrelid that the constraint applies to, if known (this is
* NULL for trigger constraints)
@@ -139,6 +136,7 @@ CATALOG(pg_constraint,2606)
* If a check constraint, source-text representation of expression
*/
text consrc;
+#endif
} FormData_pg_constraint;
/* ----------------
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index 57537c8..e8509f5 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -42,7 +42,9 @@ CATALOG(pg_database,1262) BKI_SHARED_RELATION BKI_ROWTYPE_OID(1248) BKI_SCHEMA_M
Oid datlastsysoid; /* highest OID to consider a system OID */
TransactionId datfrozenxid; /* all Xids < this are frozen in this DB */
Oid dattablespace; /* default table space for this DB */
- aclitem datacl[1]; /* access permissions (VAR LENGTH) */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ aclitem datacl[1]; /* access permissions */
+#endif
} FormData_pg_database;
/* ----------------
diff --git a/src/include/catalog/pg_db_role_setting.h b/src/include/catalog/pg_db_role_setting.h
index 1924043..c6e2f3b 100644
--- a/src/include/catalog/pg_db_role_setting.h
+++ b/src/include/catalog/pg_db_role_setting.h
@@ -35,7 +35,9 @@ CATALOG(pg_db_role_setting,2964) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
{
Oid setdatabase; /* database */
Oid setrole; /* role */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text setconfig[1]; /* GUC settings to apply at login */
+#endif
} FormData_pg_db_role_setting;
typedef FormData_pg_db_role_setting *Form_pg_db_role_setting;
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index 9fd207d..f36ce52 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -32,12 +32,9 @@ CATALOG(pg_default_acl,826)
Oid defaclrole; /* OID of role owning this ACL */
Oid defaclnamespace; /* OID of namespace, or 0 for all */
char defaclobjtype; /* see DEFACLOBJ_xxx constants below */
-
- /*
- * VARIABLE LENGTH FIELDS start here.
- */
-
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
aclitem defaclacl[1]; /* permissions to add at CREATE time */
+#endif
} FormData_pg_default_acl;
/* ----------------
diff --git a/src/include/catalog/pg_description.h b/src/include/catalog/pg_description.h
index 0e06500..352c517 100644
--- a/src/include/catalog/pg_description.h
+++ b/src/include/catalog/pg_description.h
@@ -50,7 +50,9 @@ CATALOG(pg_description,2609) BKI_WITHOUT_OIDS
Oid objoid; /* OID of object itself */
Oid classoid; /* OID of table containing object */
int4 objsubid; /* column number, or 0 if not used */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text description; /* description of object */
+#endif
} FormData_pg_description;
/* ----------------
diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h
index 606ed9a..812ccad 100644
--- a/src/include/catalog/pg_extension.h
+++ b/src/include/catalog/pg_extension.h
@@ -34,15 +34,11 @@ CATALOG(pg_extension,3079)
Oid extowner; /* extension owner */
Oid extnamespace; /* namespace of contained objects */
bool extrelocatable; /* if true, allow ALTER EXTENSION SET SCHEMA */
-
- /*
- * VARIABLE LENGTH FIELDS start here.
- *
- * extversion should never be null, but the others can be.
- */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text extversion; /* extension version name */
Oid extconfig[1]; /* dumpable configuration tables */
text extcondition[1]; /* WHERE clauses for config tables */
+#endif
} FormData_pg_extension;
/* ----------------
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index 90a51a2..b6dd8eb 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -34,11 +34,10 @@ CATALOG(pg_foreign_data_wrapper,2328)
Oid fdwowner; /* FDW owner */
Oid fdwhandler; /* handler function, or 0 if none */
Oid fdwvalidator; /* option validation function, or 0 if none */
-
- /* VARIABLE LENGTH FIELDS start here. */
-
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
aclitem fdwacl[1]; /* access permissions */
text fdwoptions[1]; /* FDW options */
+#endif
} FormData_pg_foreign_data_wrapper;
/* ----------------
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index a96328c..dd1e65e 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -31,14 +31,12 @@ CATALOG(pg_foreign_server,1417)
NameData srvname; /* foreign server name */
Oid srvowner; /* server owner */
Oid srvfdw; /* server FDW */
-
- /*
- * VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
- */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text srvtype;
text srvversion;
aclitem srvacl[1]; /* access permissions */
text srvoptions[1]; /* FDW-specific options */
+#endif
} FormData_pg_foreign_server;
/* ----------------
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index 71992d3..9af983e 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -30,7 +30,9 @@ CATALOG(pg_foreign_table,3118) BKI_WITHOUT_OIDS
{
Oid ftrelid; /* OID of foreign table */
Oid ftserver; /* OID of foreign server */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text ftoptions[1]; /* FDW-specific options */
+#endif
} FormData_pg_foreign_table;
/* ----------------
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index 6c301ff..92ca22c 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -42,8 +42,9 @@ CATALOG(pg_index,2610) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO
bool indcheckxmin; /* must we wait for xmin to be old? */
bool indisready; /* is this index ready for inserts? */
- /* VARIABLE LENGTH FIELDS: */
+ /* variable-length fields start here, but we allow direct access to indkey */
int2vector indkey; /* column numbers of indexed cols, or 0 */
+#ifdef CATALOG_VARLEN
oidvector indcollation; /* collation identifiers */
oidvector indclass; /* opclass identifiers */
int2vector indoption; /* per-column flags (AM-specific meanings) */
@@ -52,6 +53,7 @@ CATALOG(pg_index,2610) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO
* each zero entry in indkey[] */
pg_node_tree indpred; /* expression tree for predicate, if a partial
* index; else NULL */
+#endif
} FormData_pg_index;
/* ----------------
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index fd8ea0b..eb4ae5a 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -37,7 +37,9 @@ CATALOG(pg_language,2612)
Oid lanplcallfoid; /* Call handler for PL */
Oid laninline; /* Optional anonymous-block handler function */
Oid lanvalidator; /* Optional validation function */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
aclitem lanacl[1]; /* Access privileges */
+#endif
} FormData_pg_language;
/* ----------------
diff --git a/src/include/catalog/pg_largeobject.h b/src/include/catalog/pg_largeobject.h
index 7c53e1e..b89d4ec 100644
--- a/src/include/catalog/pg_largeobject.h
+++ b/src/include/catalog/pg_largeobject.h
@@ -32,6 +32,7 @@ CATALOG(pg_largeobject,2613) BKI_WITHOUT_OIDS
{
Oid loid; /* Identifier of large object */
int4 pageno; /* Page number (starting from 0) */
+ /* data has variable length, but we allow direct access; see inv_api.c */
bytea data; /* Data for page (may be zero-length) */
} FormData_pg_largeobject;
diff --git a/src/include/catalog/pg_largeobject_metadata.h b/src/include/catalog/pg_largeobject_metadata.h
index dea4d12..c280176 100644
--- a/src/include/catalog/pg_largeobject_metadata.h
+++ b/src/include/catalog/pg_largeobject_metadata.h
@@ -31,7 +31,9 @@
CATALOG(pg_largeobject_metadata,2995)
{
Oid lomowner; /* OID of the largeobject owner */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
aclitem lomacl[1]; /* access permissions */
+#endif
} FormData_pg_largeobject_metadata;
/* ----------------
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index 52a97f1..aad76a1 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -37,7 +37,9 @@ CATALOG(pg_namespace,2615)
{
NameData nspname;
Oid nspowner;
- aclitem nspacl[1]; /* VARIABLE LENGTH FIELD */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ aclitem nspacl[1];
+#endif
} FormData_pg_namespace;
/* ----------------
diff --git a/src/include/catalog/pg_pltemplate.h b/src/include/catalog/pg_pltemplate.h
index ce249c0..00abd53 100644
--- a/src/include/catalog/pg_pltemplate.h
+++ b/src/include/catalog/pg_pltemplate.h
@@ -33,11 +33,13 @@ CATALOG(pg_pltemplate,1136) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
NameData tmplname; /* name of PL */
bool tmpltrusted; /* PL is trusted? */
bool tmpldbacreate; /* PL is installable by db owner? */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text tmplhandler; /* name of call handler function */
text tmplinline; /* name of anonymous-block handler, or NULL */
text tmplvalidator; /* name of validator function, or NULL */
text tmpllibrary; /* path of shared library */
aclitem tmplacl[1]; /* access privileges for template */
+#endif
} FormData_pg_pltemplate;
/* ----------------
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index ba4f5b6..5e880d2 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -53,8 +53,9 @@ CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO
int2 pronargdefaults; /* number of arguments with defaults */
Oid prorettype; /* OID of result type */
- /* VARIABLE LENGTH FIELDS: */
+ /* variable-length fields start here, but we allow direct access to proargtypes */
oidvector proargtypes; /* parameter types (excludes OUT params) */
+#ifdef CATALOG_VARLEN
Oid proallargtypes[1]; /* all param types (NULL if IN only) */
char proargmodes[1]; /* parameter modes (NULL if IN only) */
text proargnames[1]; /* parameter names (NULL if no names) */
@@ -64,6 +65,7 @@ CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO
text probin; /* secondary procedure info (can be NULL) */
text proconfig[1]; /* procedure-local GUC settings */
aclitem proacl[1]; /* access permissions */
+#endif
} FormData_pg_proc;
/* ----------------
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index eb16b2d..e04ba81 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -39,10 +39,10 @@ CATALOG(pg_rewrite,2618)
char ev_type;
char ev_enabled;
bool is_instead;
-
- /* NB: remaining fields must be accessed via heap_getattr */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
pg_node_tree ev_qual;
pg_node_tree ev_action;
+#endif
} FormData_pg_rewrite;
/* ----------------
diff --git a/src/include/catalog/pg_seclabel.h b/src/include/catalog/pg_seclabel.h
index b468d69..101ec3c 100644
--- a/src/include/catalog/pg_seclabel.h
+++ b/src/include/catalog/pg_seclabel.h
@@ -25,8 +25,10 @@ CATALOG(pg_seclabel,3596) BKI_WITHOUT_OIDS
Oid objoid; /* OID of the object itself */
Oid classoid; /* OID of table containing the object */
int4 objsubid; /* column number, or 0 if not used */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text provider; /* name of label provider */
text label; /* security label of the object */
+#endif
} FormData_pg_seclabel;
/* ----------------
diff --git a/src/include/catalog/pg_shdescription.h b/src/include/catalog/pg_shdescription.h
index 6d0ee3b..377f433 100644
--- a/src/include/catalog/pg_shdescription.h
+++ b/src/include/catalog/pg_shdescription.h
@@ -42,7 +42,9 @@ CATALOG(pg_shdescription,2396) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
{
Oid objoid; /* OID of object itself */
Oid classoid; /* OID of table containing object */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text description; /* description of object */
+#endif
} FormData_pg_shdescription;
/* ----------------
diff --git a/src/include/catalog/pg_shseclabel.h b/src/include/catalog/pg_shseclabel.h
index 235564f..d7c49e7 100644
--- a/src/include/catalog/pg_shseclabel.h
+++ b/src/include/catalog/pg_shseclabel.h
@@ -24,8 +24,10 @@ CATALOG(pg_shseclabel,3592) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
{
Oid objoid; /* OID of the shared object itself */
Oid classoid; /* OID of table containing the shared object */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text provider; /* name of label provider */
text label; /* security label of the object */
+#endif
} FormData_pg_shseclabel;
/* ----------------
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 7d1d127..0b15b00 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -116,6 +116,7 @@ CATALOG(pg_statistic,2619) BKI_WITHOUT_OIDS
float4 stanumbers3[1];
float4 stanumbers4[1];
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
/*
* Values in these arrays are values of the column's data type. We
* presently have to cheat quite a bit to allow polymorphic arrays of this
@@ -125,6 +126,7 @@ CATALOG(pg_statistic,2619) BKI_WITHOUT_OIDS
anyarray stavalues2;
anyarray stavalues3;
anyarray stavalues4;
+#endif
} FormData_pg_statistic;
#define STATISTIC_NUM_SLOTS 4
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index a6a0686..0650a5f 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -32,8 +32,10 @@ CATALOG(pg_tablespace,1213) BKI_SHARED_RELATION
{
NameData spcname; /* tablespace name */
Oid spcowner; /* owner of tablespace */
- aclitem spcacl[1]; /* access permissions (VAR LENGTH) */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
+ aclitem spcacl[1]; /* access permissions */
text spcoptions[1]; /* per-tablespace options */
+#endif
} FormData_pg_tablespace;
/* ----------------
diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h
index 1f29d21..0ee5b8a 100644
--- a/src/include/catalog/pg_trigger.h
+++ b/src/include/catalog/pg_trigger.h
@@ -50,10 +50,13 @@ CATALOG(pg_trigger,2620)
bool tginitdeferred; /* constraint trigger is deferred initially */
int2 tgnargs; /* # of extra arguments in tgargs */
- /* VARIABLE LENGTH FIELDS (note: tgattr and tgargs must not be null) */
+ /* Variable-length fields start here, but we allow direct access to tgattr.
+ * Note: tgattr and tgargs must not be null. */
int2vector tgattr; /* column numbers, if trigger is on columns */
+#ifdef CATALOG_VARLEN
bytea tgargs; /* first\000second\000tgnargs\000 */
pg_node_tree tgqual; /* WHEN expression, or NULL if none */
+#endif
} FormData_pg_trigger;
/* ----------------
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
index 5036b8c..31fcdd8 100644
--- a/src/include/catalog/pg_ts_dict.h
+++ b/src/include/catalog/pg_ts_dict.h
@@ -36,7 +36,9 @@ CATALOG(pg_ts_dict,3600)
Oid dictnamespace; /* name space */
Oid dictowner; /* owner */
Oid dicttemplate; /* dictionary's template */
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text dictinitoption; /* options passed to dict_init() */
+#endif
} FormData_pg_ts_dict;
typedef FormData_pg_ts_dict *Form_pg_ts_dict;
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index e12efe4..d9855a7 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -200,12 +200,13 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
*/
Oid typcollation;
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
/*
* If typdefaultbin is not NULL, it is the nodeToString representation of
* a default expression for the type. Currently this is only used for
* domains.
*/
- pg_node_tree typdefaultbin; /* VARIABLE LENGTH FIELD */
+ pg_node_tree typdefaultbin;
/*
* typdefault is NULL if the type has no associated default value. If
@@ -215,12 +216,13 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
* external representation of the type's default value, which may be fed
* to the type's input converter to produce a constant.
*/
- text typdefault; /* VARIABLE LENGTH FIELD */
+ text typdefault;
/*
* Access permissions
*/
- aclitem typacl[1]; /* VARIABLE LENGTH FIELD */
+ aclitem typacl[1];
+#endif
} FormData_pg_type;
/* ----------------
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index 551000f..1d2f9b0 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -32,11 +32,9 @@ CATALOG(pg_user_mapping,1418)
* wanted */
Oid umserver; /* server of this mapping */
- /*
- * VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
- */
-
+#ifdef CATALOG_VARLEN /* variable-length fields start here */
text umoptions[1]; /* user mapping options */
+#endif
} FormData_pg_user_mapping;
/* ----------------
Peter Eisentraut <peter_e@gmx.net> writes:
On mån, 2012-01-09 at 14:04 -0500, Tom Lane wrote:
#ifdef CATALOG_VARLEN /* variable-length fields start here
*/to be even clearer.
What would be appropriate to add instead of those inconsistently-used
comments is explicit comments about the exception cases such as
proargtypes, to make it clear that the placement of the #ifdef
CATALOG_VARLEN is intentional and not a bug in those cases.
I implemented your suggestions in the attached patch.
This looks ready to go to me, except for one trivial nit: in
pg_extension.h, please keep the comment pointing out that extversion
should never be null.
regards, tom lane