diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-08-06 04:40:08 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-08-06 04:40:08 +0000 |
commit | c3e2a951b496f8030442f157b201cbddab5b5662 (patch) | |
tree | 0c58ce0f0e6c5c6d90d110bbc6b47c71b2bc66d3 /src/backend/utils/cache/relcache.c | |
parent | 8ae23135bc60df9104b4b8aa1171a7b9b89f4926 (diff) |
Toast all the system-table columns that seem to need it. It turns out
that giving pg_proc a toast table required solving the same problems
we'd have to solve for pg_class --- pg_proc is one of the relations
that gets bootstrapped in relcache.c. Solution is to go back at the
end of initialization and read in the *real* pg_class row to replace
the phony entry created by formrdesc(). This should work as long as
there's no need to touch any toasted values during initialization,
which seems a reasonable assumption.
Although I did not add a toast-table for every single system table
with a varlena attribute, I believe that it would work to just do
ALTER TABLE pg_class CREATE TOAST TABLE. So anyone who's really
intent on having several thousand ACL entries for a rel could do it.
NOTE: I didn't force initdb, but you must do one to see the effects
of this patch.
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r-- | src/backend/utils/cache/relcache.c | 134 |
1 files changed, 110 insertions, 24 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 84f20757d6a..59758adb62d 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,13 +8,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.108 2000/07/30 22:13:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.109 2000/08/06 04:39:03 tgl Exp $ * *------------------------------------------------------------------------- */ /* * INTERFACE ROUTINES - * RelationInitialize - initialize relcache + * RelationCacheInitialize - initialize relcache + * RelationCacheInitializePhase2 - finish initializing relcache * RelationIdCacheGetRelation - get a reldesc from the cache (id) * RelationNameCacheGetRelation - get a reldesc from the cache (name) * RelationIdGetRelation - get a reldesc by relation id @@ -217,6 +218,7 @@ static void write_irels(void); static void formrdesc(char *relationName, int natts, FormData_pg_attribute *att); +static void fixrdesc(char *relationName); static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo); static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo); @@ -1081,8 +1083,9 @@ IndexedAccessMethodInitialize(Relation relation) * formrdesc * * This is a special cut-down version of RelationBuildDesc() - * used by RelationInitialize() in initializing the relcache. - * The relation descriptor is built just from the supplied parameters. + * used by RelationCacheInitialize() in initializing the relcache. + * The relation descriptor is built just from the supplied parameters, + * without actually looking at any system table entries. * * NOTE: we assume we are already switched into CacheMemoryContext. * -------------------------------- @@ -1115,18 +1118,23 @@ formrdesc(char *relationName, RelationSetReferenceCount(relation, 1); /* ---------------- - * initialize relation tuple form + * all entries built with this routine are nailed-in-cache * ---------------- */ - relation->rd_rel = (Form_pg_class) palloc(CLASS_TUPLE_SIZE); - MemSet(relation->rd_rel, 0, CLASS_TUPLE_SIZE); - strcpy(RelationGetPhysicalRelationName(relation), relationName); + relation->rd_isnailed = true; /* ---------------- - * initialize attribute tuple form + * initialize relation tuple form + * + * The data we insert here is pretty incomplete/bogus, but it'll + * serve to get us launched. RelationCacheInitializePhase2() will + * read the real data from pg_class and replace what we've done here. * ---------------- */ - relation->rd_att = CreateTemplateTupleDesc(natts); + relation->rd_rel = (Form_pg_class) palloc(CLASS_TUPLE_SIZE); + MemSet(relation->rd_rel, 0, CLASS_TUPLE_SIZE); + + strcpy(RelationGetPhysicalRelationName(relation), relationName); /* * For debugging purposes, it's important to distinguish between @@ -1134,23 +1142,21 @@ formrdesc(char *relationName, * code in the buffer manager that traces allocations that has to know * about this. */ - if (IsSystemRelationName(relationName)) - { - relation->rd_rel->relowner = 6; /* XXX use sym const */ relation->rd_rel->relisshared = IsSharedSystemRelationName(relationName); - } else - { - relation->rd_rel->relowner = 0; relation->rd_rel->relisshared = false; - } - relation->rd_rel->relpages = 1; /* XXX */ - relation->rd_rel->reltuples = 1; /* XXX */ + relation->rd_rel->relpages = 1; + relation->rd_rel->reltuples = 1; relation->rd_rel->relkind = RELKIND_RELATION; relation->rd_rel->relnatts = (int16) natts; - relation->rd_isnailed = true; + + /* ---------------- + * initialize attribute tuple form + * ---------------- + */ + relation->rd_att = CreateTemplateTupleDesc(natts); /* ---------------- * initialize tuple desc info @@ -1187,8 +1193,8 @@ formrdesc(char *relationName, * the rdesc for pg_class must already exist. Therefore we must do * the check (and possible set) after cache insertion. * - * XXX I believe the above comment is misguided; we should be - * running in bootstrap or init processing mode, and CatalogHasIndex + * XXX I believe the above comment is misguided; we should be running + * in bootstrap or init processing mode here, and CatalogHasIndex * relies on hard-wired info in those cases. */ relation->rd_rel->relhasindex = @@ -1196,6 +1202,56 @@ formrdesc(char *relationName, } +/* -------------------------------- + * fixrdesc + * + * Update the phony data inserted by formrdesc() with real info + * from pg_class. + * -------------------------------- + */ +static void +fixrdesc(char *relationName) +{ + RelationBuildDescInfo buildinfo; + HeapTuple pg_class_tuple; + Form_pg_class relp; + Relation relation; + + /* ---------------- + * find the tuple in pg_class corresponding to the given relation name + * ---------------- + */ + buildinfo.infotype = INFO_RELNAME; + buildinfo.i.info_name = relationName; + + pg_class_tuple = ScanPgRelation(buildinfo); + + if (!HeapTupleIsValid(pg_class_tuple)) + elog(FATAL, "fixrdesc: no pg_class entry for %s", + relationName); + relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); + + /* ---------------- + * find the pre-made relcache entry (better be there!) + * ---------------- + */ + relation = RelationNameCacheGetRelation(relationName); + if (!RelationIsValid(relation)) + elog(FATAL, "fixrdesc: no existing relcache entry for %s", + relationName); + + /* ---------------- + * and copy pg_class_tuple to relation->rd_rel. + * (See notes in AllocateRelationDesc()) + * ---------------- + */ + Assert(relation->rd_rel != NULL); + memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE); + + heap_freetuple(pg_class_tuple); +} + + /* ---------------------------------------------------------------- * Relation Descriptor Lookup Interface * ---------------------------------------------------------------- @@ -1829,7 +1885,7 @@ RelationPurgeLocalRelation(bool xactCommitted) } /* -------------------------------- - * RelationInitialize + * RelationCacheInitialize * * This initializes the relation descriptor cache. * -------------------------------- @@ -1838,7 +1894,7 @@ RelationPurgeLocalRelation(bool xactCommitted) #define INITRELCACHESIZE 400 void -RelationInitialize(void) +RelationCacheInitialize(void) { MemoryContext oldcxt; HASHCTL ctl; @@ -1870,6 +1926,8 @@ RelationInitialize(void) * initialize the cache with pre-made relation descriptors * for some of the more important system relations. These * relations should always be in the cache. + * + * NB: see also the list in RelationCacheInitializePhase2(). * ---------------- */ formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class); @@ -1892,6 +1950,34 @@ RelationInitialize(void) MemoryContextSwitchTo(oldcxt); } +/* -------------------------------- + * RelationCacheInitializePhase2 + * + * This completes initialization of the relcache after catcache + * is functional and we are able to actually load data from pg_class. + * -------------------------------- + */ +void +RelationCacheInitializePhase2(void) +{ + /* + * Get the real pg_class tuple for each nailed-in-cache relcache entry + * that was made by RelationCacheInitialize(), and replace the phony + * rd_rel entry made by formrdesc(). This is necessary so that we have, + * for example, the correct toast-table info for tables that have such. + */ + if (!IsBootstrapProcessingMode()) + { + fixrdesc(RelationRelationName); + fixrdesc(AttributeRelationName); + fixrdesc(ProcedureRelationName); + fixrdesc(TypeRelationName); + /* We don't bother to update the entries for pg_variable or pg_log. */ + } +} + + + static void AttrDefaultFetch(Relation relation) { |