From 984791e0e1a52d0929b402885b250361a1ad9758 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 12 Dec 2004 05:07:50 +0000 Subject: [PATCH] Upgrade formrdesc() so that it can correctly initialize the tupledesc (rd_att) field of a nailed-in-cache relcache entry. This fixes the bug reported by Alvaro 8-Dec-2004; I believe it probably also explains Grant Finnemore's report of 10-Sep-2004. In an unrelated change in the same file, put back 7.4's response to failure to rename() the relcache init file, ie, unlink the useless temp file. I did not put back the warning message, since there might actually be some reason not to have that. --- src/backend/utils/cache/relcache.c | 62 ++++++++++++++++-------------- src/include/catalog/pg_type.h | 6 ++- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 36c11709ab..5c2d81c06e 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.212 2004/11/20 20:19:52 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.213 2004/12/12 05:07:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -257,8 +257,8 @@ static Relation RelationSysNameCacheGetRelation(const char *relationName); static bool load_relcache_init_file(void); static void write_relcache_init_file(void); -static void formrdesc(const char *relationName, int natts, - FormData_pg_attribute *att); +static void formrdesc(const char *relationName, Oid relationReltype, + bool hasoids, int natts, FormData_pg_attribute *att); static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo, bool indexOK); static Relation AllocateRelationDesc(Relation relation, Form_pg_class relp); @@ -1265,16 +1265,15 @@ LookupOpclassInfo(Oid operatorClassOid, * NOTE: we assume we are already switched into CacheMemoryContext. */ static void -formrdesc(const char *relationName, - int natts, - FormData_pg_attribute *att) +formrdesc(const char *relationName, Oid relationReltype, + bool hasoids, int natts, FormData_pg_attribute *att) { Relation relation; int i; bool has_not_null; /* - * allocate new relation desc clear all fields of reldesc + * allocate new relation desc, clear all fields of reldesc */ relation = (Relation) palloc0(sizeof(RelationData)); relation->rd_targblock = InvalidBlockNumber; @@ -1306,6 +1305,7 @@ formrdesc(const char *relationName, namestrcpy(&relation->rd_rel->relname, relationName); relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE; + relation->rd_rel->reltype = relationReltype; /* * It's important to distinguish between shared and non-shared @@ -1318,7 +1318,7 @@ formrdesc(const char *relationName, relation->rd_rel->relpages = 1; relation->rd_rel->reltuples = 1; relation->rd_rel->relkind = RELKIND_RELATION; - relation->rd_rel->relhasoids = true; + relation->rd_rel->relhasoids = hasoids; relation->rd_rel->relnatts = (int16) natts; /* @@ -1327,12 +1327,10 @@ formrdesc(const char *relationName, * Unlike the case with the relation tuple, this data had better be right * because it will never be replaced. The input values must be * correctly defined by macros in src/include/catalog/ headers. - * - * Note however that rd_att's tdtypeid, tdtypmod, tdhasoid fields are not - * right at this point. They will be fixed later when the real - * pg_class row is loaded. */ - relation->rd_att = CreateTemplateTupleDesc(natts, false); + relation->rd_att = CreateTemplateTupleDesc(natts, hasoids); + relation->rd_att->tdtypeid = relationReltype; + relation->rd_att->tdtypmod = -1; /* unnecessary, but... */ /* * initialize tuple desc info @@ -1380,10 +1378,12 @@ formrdesc(const char *relationName, /* * initialize the rel-has-index flag, using hardwired knowledge */ - relation->rd_rel->relhasindex = false; - - /* In bootstrap mode, we have no indexes */ - if (!IsBootstrapProcessingMode()) + if (IsBootstrapProcessingMode()) + { + /* In bootstrap mode, we have no indexes */ + relation->rd_rel->relhasindex = false; + } + else { /* Otherwise, all the rels formrdesc is used for have indexes */ relation->rd_rel->relhasindex = true; @@ -2348,14 +2348,14 @@ RelationCacheInitialize(void) if (IsBootstrapProcessingMode() || !load_relcache_init_file()) { - formrdesc(RelationRelationName, - Natts_pg_class, Desc_pg_class); - formrdesc(AttributeRelationName, - Natts_pg_attribute, Desc_pg_attribute); - formrdesc(ProcedureRelationName, - Natts_pg_proc, Desc_pg_proc); - formrdesc(TypeRelationName, - Natts_pg_type, Desc_pg_type); + formrdesc(RelationRelationName, PG_CLASS_RELTYPE_OID, + true, Natts_pg_class, Desc_pg_class); + formrdesc(AttributeRelationName, PG_ATTRIBUTE_RELTYPE_OID, + false, Natts_pg_attribute, Desc_pg_attribute); + formrdesc(ProcedureRelationName, PG_PROC_RELTYPE_OID, + true, Natts_pg_proc, Desc_pg_proc); + formrdesc(TypeRelationName, PG_TYPE_RELTYPE_OID, + true, Natts_pg_type, Desc_pg_type); #define NUM_CRITICAL_RELS 4 /* fix if you change list above */ } @@ -3422,16 +3422,22 @@ write_relcache_init_file(void) /* * OK, rename the temp file to its final name, deleting any * previously-existing init file. + * + * Note: a failure here is possible under Cygwin, if some other + * backend is holding open an unlinked-but-not-yet-gone init file. + * So treat this as a noncritical failure; just remove the useless + * temp file on failure. */ - rename(tempfilename, finalfilename); - LWLockRelease(RelCacheInitLock); + if (rename(tempfilename, finalfilename) < 0) + unlink(tempfilename); } else { /* Delete the already-obsolete temp file */ unlink(tempfilename); - LWLockRelease(RelCacheInitLock); } + + LWLockRelease(RelCacheInitLock); } /* diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 67c93d08a7..aa41720d86 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.156 2004/08/29 05:06:55 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.157 2004/12/12 05:07:50 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -305,9 +305,13 @@ DESCR("array of INDEX_MAX_KEYS oids, used in system tables"); #define OIDVECTOROID 30 DATA(insert OID = 71 ( pg_type PGNSP PGUID -1 f c t \054 1247 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ )); +#define PG_TYPE_RELTYPE_OID 71 DATA(insert OID = 75 ( pg_attribute PGNSP PGUID -1 f c t \054 1249 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ )); +#define PG_ATTRIBUTE_RELTYPE_OID 75 DATA(insert OID = 81 ( pg_proc PGNSP PGUID -1 f c t \054 1255 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ )); +#define PG_PROC_RELTYPE_OID 81 DATA(insert OID = 83 ( pg_class PGNSP PGUID -1 f c t \054 1259 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ )); +#define PG_CLASS_RELTYPE_OID 83 DATA(insert OID = 86 ( pg_shadow PGNSP PGUID -1 f c t \054 1260 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 87 ( pg_group PGNSP PGUID -1 f c t \054 1261 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ )); DATA(insert OID = 88 ( pg_database PGNSP PGUID -1 f c t \054 1262 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ )); -- 2.40.0