8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.108 2000/07/30 22:13:55 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.109 2000/08/06 04:39:03 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
15
15
/*
16
16
* INTERFACE ROUTINES
17
- * RelationInitialize - initialize relcache
17
+ * RelationCacheInitialize - initialize relcache
18
+ * RelationCacheInitializePhase2 - finish initializing relcache
18
19
* RelationIdCacheGetRelation - get a reldesc from the cache (id)
19
20
* RelationNameCacheGetRelation - get a reldesc from the cache (name)
20
21
* RelationIdGetRelation - get a reldesc by relation id
@@ -217,6 +218,7 @@ static void write_irels(void);
217
218
218
219
static void formrdesc (char * relationName , int natts ,
219
220
FormData_pg_attribute * att );
221
+ static void fixrdesc (char * relationName );
220
222
221
223
static HeapTuple ScanPgRelation (RelationBuildDescInfo buildinfo );
222
224
static HeapTuple scan_pg_rel_seq (RelationBuildDescInfo buildinfo );
@@ -1081,8 +1083,9 @@ IndexedAccessMethodInitialize(Relation relation)
1081
1083
* formrdesc
1082
1084
*
1083
1085
* This is a special cut-down version of RelationBuildDesc()
1084
- * used by RelationInitialize() in initializing the relcache.
1085
- * The relation descriptor is built just from the supplied parameters.
1086
+ * used by RelationCacheInitialize() in initializing the relcache.
1087
+ * The relation descriptor is built just from the supplied parameters,
1088
+ * without actually looking at any system table entries.
1086
1089
*
1087
1090
* NOTE: we assume we are already switched into CacheMemoryContext.
1088
1091
* --------------------------------
@@ -1115,42 +1118,45 @@ formrdesc(char *relationName,
1115
1118
RelationSetReferenceCount (relation , 1 );
1116
1119
1117
1120
/* ----------------
1118
- * initialize relation tuple form
1121
+ * all entries built with this routine are nailed-in-cache
1119
1122
* ----------------
1120
1123
*/
1121
- relation -> rd_rel = (Form_pg_class ) palloc (CLASS_TUPLE_SIZE );
1122
- MemSet (relation -> rd_rel , 0 , CLASS_TUPLE_SIZE );
1123
- strcpy (RelationGetPhysicalRelationName (relation ), relationName );
1124
+ relation -> rd_isnailed = true;
1124
1125
1125
1126
/* ----------------
1126
- * initialize attribute tuple form
1127
+ * initialize relation tuple form
1128
+ *
1129
+ * The data we insert here is pretty incomplete/bogus, but it'll
1130
+ * serve to get us launched. RelationCacheInitializePhase2() will
1131
+ * read the real data from pg_class and replace what we've done here.
1127
1132
* ----------------
1128
1133
*/
1129
- relation -> rd_att = CreateTemplateTupleDesc (natts );
1134
+ relation -> rd_rel = (Form_pg_class ) palloc (CLASS_TUPLE_SIZE );
1135
+ MemSet (relation -> rd_rel , 0 , CLASS_TUPLE_SIZE );
1136
+
1137
+ strcpy (RelationGetPhysicalRelationName (relation ), relationName );
1130
1138
1131
1139
/*
1132
1140
* For debugging purposes, it's important to distinguish between
1133
1141
* shared and non-shared relations, even at bootstrap time. There's
1134
1142
* code in the buffer manager that traces allocations that has to know
1135
1143
* about this.
1136
1144
*/
1137
-
1138
1145
if (IsSystemRelationName (relationName ))
1139
- {
1140
- relation -> rd_rel -> relowner = 6 ; /* XXX use sym const */
1141
1146
relation -> rd_rel -> relisshared = IsSharedSystemRelationName (relationName );
1142
- }
1143
1147
else
1144
- {
1145
- relation -> rd_rel -> relowner = 0 ;
1146
1148
relation -> rd_rel -> relisshared = false;
1147
- }
1148
1149
1149
- relation -> rd_rel -> relpages = 1 ; /* XXX */
1150
- relation -> rd_rel -> reltuples = 1 ; /* XXX */
1150
+ relation -> rd_rel -> relpages = 1 ;
1151
+ relation -> rd_rel -> reltuples = 1 ;
1151
1152
relation -> rd_rel -> relkind = RELKIND_RELATION ;
1152
1153
relation -> rd_rel -> relnatts = (int16 ) natts ;
1153
- relation -> rd_isnailed = true;
1154
+
1155
+ /* ----------------
1156
+ * initialize attribute tuple form
1157
+ * ----------------
1158
+ */
1159
+ relation -> rd_att = CreateTemplateTupleDesc (natts );
1154
1160
1155
1161
/* ----------------
1156
1162
* initialize tuple desc info
@@ -1187,15 +1193,65 @@ formrdesc(char *relationName,
1187
1193
* the rdesc for pg_class must already exist. Therefore we must do
1188
1194
* the check (and possible set) after cache insertion.
1189
1195
*
1190
- * XXX I believe the above comment is misguided; we should be
1191
- * running in bootstrap or init processing mode, and CatalogHasIndex
1196
+ * XXX I believe the above comment is misguided; we should be running
1197
+ * in bootstrap or init processing mode here , and CatalogHasIndex
1192
1198
* relies on hard-wired info in those cases.
1193
1199
*/
1194
1200
relation -> rd_rel -> relhasindex =
1195
1201
CatalogHasIndex (relationName , RelationGetRelid (relation ));
1196
1202
}
1197
1203
1198
1204
1205
+ /* --------------------------------
1206
+ * fixrdesc
1207
+ *
1208
+ * Update the phony data inserted by formrdesc() with real info
1209
+ * from pg_class.
1210
+ * --------------------------------
1211
+ */
1212
+ static void
1213
+ fixrdesc (char * relationName )
1214
+ {
1215
+ RelationBuildDescInfo buildinfo ;
1216
+ HeapTuple pg_class_tuple ;
1217
+ Form_pg_class relp ;
1218
+ Relation relation ;
1219
+
1220
+ /* ----------------
1221
+ * find the tuple in pg_class corresponding to the given relation name
1222
+ * ----------------
1223
+ */
1224
+ buildinfo .infotype = INFO_RELNAME ;
1225
+ buildinfo .i .info_name = relationName ;
1226
+
1227
+ pg_class_tuple = ScanPgRelation (buildinfo );
1228
+
1229
+ if (!HeapTupleIsValid (pg_class_tuple ))
1230
+ elog (FATAL , "fixrdesc: no pg_class entry for %s" ,
1231
+ relationName );
1232
+ relp = (Form_pg_class ) GETSTRUCT (pg_class_tuple );
1233
+
1234
+ /* ----------------
1235
+ * find the pre-made relcache entry (better be there!)
1236
+ * ----------------
1237
+ */
1238
+ relation = RelationNameCacheGetRelation (relationName );
1239
+ if (!RelationIsValid (relation ))
1240
+ elog (FATAL , "fixrdesc: no existing relcache entry for %s" ,
1241
+ relationName );
1242
+
1243
+ /* ----------------
1244
+ * and copy pg_class_tuple to relation->rd_rel.
1245
+ * (See notes in AllocateRelationDesc())
1246
+ * ----------------
1247
+ */
1248
+ Assert (relation -> rd_rel != NULL );
1249
+ memcpy ((char * ) relation -> rd_rel , (char * ) relp , CLASS_TUPLE_SIZE );
1250
+
1251
+ heap_freetuple (pg_class_tuple );
1252
+ }
1253
+
1254
+
1199
1255
/* ----------------------------------------------------------------
1200
1256
* Relation Descriptor Lookup Interface
1201
1257
* ----------------------------------------------------------------
@@ -1829,7 +1885,7 @@ RelationPurgeLocalRelation(bool xactCommitted)
1829
1885
}
1830
1886
1831
1887
/* --------------------------------
1832
- * RelationInitialize
1888
+ * RelationCacheInitialize
1833
1889
*
1834
1890
* This initializes the relation descriptor cache.
1835
1891
* --------------------------------
@@ -1838,7 +1894,7 @@ RelationPurgeLocalRelation(bool xactCommitted)
1838
1894
#define INITRELCACHESIZE 400
1839
1895
1840
1896
void
1841
- RelationInitialize (void )
1897
+ RelationCacheInitialize (void )
1842
1898
{
1843
1899
MemoryContext oldcxt ;
1844
1900
HASHCTL ctl ;
@@ -1870,6 +1926,8 @@ RelationInitialize(void)
1870
1926
* initialize the cache with pre-made relation descriptors
1871
1927
* for some of the more important system relations. These
1872
1928
* relations should always be in the cache.
1929
+ *
1930
+ * NB: see also the list in RelationCacheInitializePhase2().
1873
1931
* ----------------
1874
1932
*/
1875
1933
formrdesc (RelationRelationName , Natts_pg_class , Desc_pg_class );
@@ -1892,6 +1950,34 @@ RelationInitialize(void)
1892
1950
MemoryContextSwitchTo (oldcxt );
1893
1951
}
1894
1952
1953
+ /* --------------------------------
1954
+ * RelationCacheInitializePhase2
1955
+ *
1956
+ * This completes initialization of the relcache after catcache
1957
+ * is functional and we are able to actually load data from pg_class.
1958
+ * --------------------------------
1959
+ */
1960
+ void
1961
+ RelationCacheInitializePhase2 (void )
1962
+ {
1963
+ /*
1964
+ * Get the real pg_class tuple for each nailed-in-cache relcache entry
1965
+ * that was made by RelationCacheInitialize(), and replace the phony
1966
+ * rd_rel entry made by formrdesc(). This is necessary so that we have,
1967
+ * for example, the correct toast-table info for tables that have such.
1968
+ */
1969
+ if (!IsBootstrapProcessingMode ())
1970
+ {
1971
+ fixrdesc (RelationRelationName );
1972
+ fixrdesc (AttributeRelationName );
1973
+ fixrdesc (ProcedureRelationName );
1974
+ fixrdesc (TypeRelationName );
1975
+ /* We don't bother to update the entries for pg_variable or pg_log. */
1976
+ }
1977
+ }
1978
+
1979
+
1980
+
1895
1981
static void
1896
1982
AttrDefaultFetch (Relation relation )
1897
1983
{
0 commit comments