Commit 984791e0 authored by Tom Lane's avatar Tom Lane

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.
parent 12b1b5d8
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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); ...@@ -257,8 +257,8 @@ static Relation RelationSysNameCacheGetRelation(const char *relationName);
static bool load_relcache_init_file(void); static bool load_relcache_init_file(void);
static void write_relcache_init_file(void); static void write_relcache_init_file(void);
static void formrdesc(const char *relationName, int natts, static void formrdesc(const char *relationName, Oid relationReltype,
FormData_pg_attribute *att); bool hasoids, int natts, FormData_pg_attribute *att);
static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo, bool indexOK); static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo, bool indexOK);
static Relation AllocateRelationDesc(Relation relation, Form_pg_class relp); static Relation AllocateRelationDesc(Relation relation, Form_pg_class relp);
...@@ -1265,16 +1265,15 @@ LookupOpclassInfo(Oid operatorClassOid, ...@@ -1265,16 +1265,15 @@ LookupOpclassInfo(Oid operatorClassOid,
* NOTE: we assume we are already switched into CacheMemoryContext. * NOTE: we assume we are already switched into CacheMemoryContext.
*/ */
static void static void
formrdesc(const char *relationName, formrdesc(const char *relationName, Oid relationReltype,
int natts, bool hasoids, int natts, FormData_pg_attribute *att)
FormData_pg_attribute *att)
{ {
Relation relation; Relation relation;
int i; int i;
bool has_not_null; 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 = (Relation) palloc0(sizeof(RelationData));
relation->rd_targblock = InvalidBlockNumber; relation->rd_targblock = InvalidBlockNumber;
...@@ -1306,6 +1305,7 @@ formrdesc(const char *relationName, ...@@ -1306,6 +1305,7 @@ formrdesc(const char *relationName,
namestrcpy(&relation->rd_rel->relname, relationName); namestrcpy(&relation->rd_rel->relname, relationName);
relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE; relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
relation->rd_rel->reltype = relationReltype;
/* /*
* It's important to distinguish between shared and non-shared * It's important to distinguish between shared and non-shared
...@@ -1318,7 +1318,7 @@ formrdesc(const char *relationName, ...@@ -1318,7 +1318,7 @@ formrdesc(const char *relationName,
relation->rd_rel->relpages = 1; relation->rd_rel->relpages = 1;
relation->rd_rel->reltuples = 1; relation->rd_rel->reltuples = 1;
relation->rd_rel->relkind = RELKIND_RELATION; relation->rd_rel->relkind = RELKIND_RELATION;
relation->rd_rel->relhasoids = true; relation->rd_rel->relhasoids = hasoids;
relation->rd_rel->relnatts = (int16) natts; relation->rd_rel->relnatts = (int16) natts;
/* /*
...@@ -1327,12 +1327,10 @@ formrdesc(const char *relationName, ...@@ -1327,12 +1327,10 @@ formrdesc(const char *relationName,
* Unlike the case with the relation tuple, this data had better be right * Unlike the case with the relation tuple, this data had better be right
* because it will never be replaced. The input values must be * because it will never be replaced. The input values must be
* correctly defined by macros in src/include/catalog/ headers. * 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 * initialize tuple desc info
...@@ -1380,10 +1378,12 @@ formrdesc(const char *relationName, ...@@ -1380,10 +1378,12 @@ formrdesc(const char *relationName,
/* /*
* initialize the rel-has-index flag, using hardwired knowledge * initialize the rel-has-index flag, using hardwired knowledge
*/ */
relation->rd_rel->relhasindex = false; if (IsBootstrapProcessingMode())
{
/* In bootstrap mode, we have no indexes */ /* In bootstrap mode, we have no indexes */
if (!IsBootstrapProcessingMode()) relation->rd_rel->relhasindex = false;
}
else
{ {
/* Otherwise, all the rels formrdesc is used for have indexes */ /* Otherwise, all the rels formrdesc is used for have indexes */
relation->rd_rel->relhasindex = true; relation->rd_rel->relhasindex = true;
...@@ -2348,14 +2348,14 @@ RelationCacheInitialize(void) ...@@ -2348,14 +2348,14 @@ RelationCacheInitialize(void)
if (IsBootstrapProcessingMode() || if (IsBootstrapProcessingMode() ||
!load_relcache_init_file()) !load_relcache_init_file())
{ {
formrdesc(RelationRelationName, formrdesc(RelationRelationName, PG_CLASS_RELTYPE_OID,
Natts_pg_class, Desc_pg_class); true, Natts_pg_class, Desc_pg_class);
formrdesc(AttributeRelationName, formrdesc(AttributeRelationName, PG_ATTRIBUTE_RELTYPE_OID,
Natts_pg_attribute, Desc_pg_attribute); false, Natts_pg_attribute, Desc_pg_attribute);
formrdesc(ProcedureRelationName, formrdesc(ProcedureRelationName, PG_PROC_RELTYPE_OID,
Natts_pg_proc, Desc_pg_proc); true, Natts_pg_proc, Desc_pg_proc);
formrdesc(TypeRelationName, formrdesc(TypeRelationName, PG_TYPE_RELTYPE_OID,
Natts_pg_type, Desc_pg_type); true, Natts_pg_type, Desc_pg_type);
#define NUM_CRITICAL_RELS 4 /* fix if you change list above */ #define NUM_CRITICAL_RELS 4 /* fix if you change list above */
} }
...@@ -3422,16 +3422,22 @@ write_relcache_init_file(void) ...@@ -3422,16 +3422,22 @@ write_relcache_init_file(void)
/* /*
* OK, rename the temp file to its final name, deleting any * OK, rename the temp file to its final name, deleting any
* previously-existing init file. * 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); if (rename(tempfilename, finalfilename) < 0)
LWLockRelease(RelCacheInitLock); unlink(tempfilename);
} }
else else
{ {
/* Delete the already-obsolete temp file */ /* Delete the already-obsolete temp file */
unlink(tempfilename); unlink(tempfilename);
LWLockRelease(RelCacheInitLock);
} }
LWLockRelease(RelCacheInitLock);
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 * NOTES
* the genbki.sh script reads this file and generates .bki * 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"); ...@@ -305,9 +305,13 @@ DESCR("array of INDEX_MAX_KEYS oids, used in system tables");
#define OIDVECTOROID 30 #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_ )); 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_ )); 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_ )); 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_ )); 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 = 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 = 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_ )); 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_ ));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment