Skip to content

Commit c3e2a95

Browse files
committed
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.
1 parent 8ae2313 commit c3e2a95

File tree

6 files changed

+168
-78
lines changed

6 files changed

+168
-78
lines changed

src/backend/commands/analyze.c

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.3 2000/07/05 23:11:08 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.4 2000/08/06 04:40:08 tgl Exp $
1212
*
1313
1414
*-------------------------------------------------------------------------
@@ -106,7 +106,7 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
106106
elog(NOTICE, "Skipping \"%s\" --- only table owner can VACUUM it",
107107
RelationGetRelationName(onerel));
108108
*/
109-
heap_close(onerel, AccessExclusiveLock);
109+
heap_close(onerel, NoLock);
110110
CommitTransactionCommand();
111111
return;
112112
}
@@ -220,7 +220,8 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
220220

221221
heap_endscan(scan);
222222

223-
heap_close(onerel, AccessShareLock);
223+
/* close rel, but keep lock so it doesn't go away before commit */
224+
heap_close(onerel, NoLock);
224225

225226
/* update statistics in pg_class */
226227
update_attstats(relid, attr_cnt, vacattrstats);
@@ -388,8 +389,8 @@ bucketcpy(Form_pg_attribute attr, Datum value, Datum *bucket, int *bucket_len)
388389
/*
389390
* update_attstats() -- update attribute statistics for one relation
390391
*
391-
* Updates of pg_attribute statistics are handled by over-write.
392-
* for reasons described above.
392+
* Updates of pg_attribute statistics are handled by over-write,
393+
* for reasons described above. pg_statistic rows are added normally.
393394
*
394395
* To keep things simple, we punt for pg_statistic, and don't try
395396
* to compute or store rows for pg_statistic itself in pg_statistic.
@@ -510,7 +511,7 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
510511
* deleted all the pg_statistic tuples for the rel, so we
511512
* just have to insert new ones here.
512513
*
513-
* Note vacuum_rel() has seen to it that we won't come here
514+
* Note analyze_rel() has seen to it that we won't come here
514515
* when vacuuming pg_statistic itself.
515516
*/
516517
if (VacAttrStatsLtGtValid(stats) && stats->initialized)
@@ -524,6 +525,7 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
524525
nonnull_cnt_d = stats->nonnull_cnt; /* prevent overflow */
525526
Datum values[Natts_pg_statistic];
526527
char nulls[Natts_pg_statistic];
528+
Relation irelations[Num_pg_statistic_indices];
527529

528530
nullratio = null_cnt_d / (nonnull_cnt_d + null_cnt_d);
529531
bestratio = best_cnt_d / (nonnull_cnt_d + null_cnt_d);
@@ -567,31 +569,12 @@ update_attstats(Oid relid, int natts, VacAttrStats *vacattrstats)
567569

568570
stup = heap_formtuple(sd->rd_att, values, nulls);
569571

570-
/* ----------------
571-
* Watch out for oversize tuple, which can happen if
572-
* all three of the saved data values are long.
573-
* Our fallback strategy is just to not store the
574-
* pg_statistic tuple at all in that case. (We could
575-
* replace the values by NULLs and still store the
576-
* numeric stats, but presently selfuncs.c couldn't
577-
* do anything useful with that case anyway.)
578-
*
579-
* We could reduce the probability of overflow, but not
580-
* prevent it, by storing the data values as compressed
581-
* text; is that worth doing? The problem should go
582-
* away whenever long tuples get implemented...
583-
* ----------------
584-
*/
585-
if (MAXALIGN(stup->t_len) <= MaxTupleSize)
586-
{
587-
/* OK, store tuple and update indexes too */
588-
Relation irelations[Num_pg_statistic_indices];
572+
/* store tuple and update indexes too */
573+
heap_insert(sd, stup);
589574

590-
heap_insert(sd, stup);
591-
CatalogOpenIndices(Num_pg_statistic_indices, Name_pg_statistic_indices, irelations);
592-
CatalogIndexInsert(irelations, Num_pg_statistic_indices, sd, stup);
593-
CatalogCloseIndices(Num_pg_statistic_indices, irelations);
594-
}
575+
CatalogOpenIndices(Num_pg_statistic_indices, Name_pg_statistic_indices, irelations);
576+
CatalogIndexInsert(irelations, Num_pg_statistic_indices, sd, stup);
577+
CatalogCloseIndices(Num_pg_statistic_indices, irelations);
595578

596579
/* release allocated space */
597580
pfree(DatumGetPointer(values[Anum_pg_statistic_stacommonval - 1]));

src/backend/utils/cache/relcache.c

Lines changed: 110 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
*
99
*
1010
* 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 $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515
/*
1616
* INTERFACE ROUTINES
17-
* RelationInitialize - initialize relcache
17+
* RelationCacheInitialize - initialize relcache
18+
* RelationCacheInitializePhase2 - finish initializing relcache
1819
* RelationIdCacheGetRelation - get a reldesc from the cache (id)
1920
* RelationNameCacheGetRelation - get a reldesc from the cache (name)
2021
* RelationIdGetRelation - get a reldesc by relation id
@@ -217,6 +218,7 @@ static void write_irels(void);
217218

218219
static void formrdesc(char *relationName, int natts,
219220
FormData_pg_attribute *att);
221+
static void fixrdesc(char *relationName);
220222

221223
static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo);
222224
static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo);
@@ -1081,8 +1083,9 @@ IndexedAccessMethodInitialize(Relation relation)
10811083
* formrdesc
10821084
*
10831085
* 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.
10861089
*
10871090
* NOTE: we assume we are already switched into CacheMemoryContext.
10881091
* --------------------------------
@@ -1115,42 +1118,45 @@ formrdesc(char *relationName,
11151118
RelationSetReferenceCount(relation, 1);
11161119

11171120
/* ----------------
1118-
* initialize relation tuple form
1121+
* all entries built with this routine are nailed-in-cache
11191122
* ----------------
11201123
*/
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;
11241125

11251126
/* ----------------
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.
11271132
* ----------------
11281133
*/
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);
11301138

11311139
/*
11321140
* For debugging purposes, it's important to distinguish between
11331141
* shared and non-shared relations, even at bootstrap time. There's
11341142
* code in the buffer manager that traces allocations that has to know
11351143
* about this.
11361144
*/
1137-
11381145
if (IsSystemRelationName(relationName))
1139-
{
1140-
relation->rd_rel->relowner = 6; /* XXX use sym const */
11411146
relation->rd_rel->relisshared = IsSharedSystemRelationName(relationName);
1142-
}
11431147
else
1144-
{
1145-
relation->rd_rel->relowner = 0;
11461148
relation->rd_rel->relisshared = false;
1147-
}
11481149

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;
11511152
relation->rd_rel->relkind = RELKIND_RELATION;
11521153
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);
11541160

11551161
/* ----------------
11561162
* initialize tuple desc info
@@ -1187,15 +1193,65 @@ formrdesc(char *relationName,
11871193
* the rdesc for pg_class must already exist. Therefore we must do
11881194
* the check (and possible set) after cache insertion.
11891195
*
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
11921198
* relies on hard-wired info in those cases.
11931199
*/
11941200
relation->rd_rel->relhasindex =
11951201
CatalogHasIndex(relationName, RelationGetRelid(relation));
11961202
}
11971203

11981204

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+
11991255
/* ----------------------------------------------------------------
12001256
* Relation Descriptor Lookup Interface
12011257
* ----------------------------------------------------------------
@@ -1829,7 +1885,7 @@ RelationPurgeLocalRelation(bool xactCommitted)
18291885
}
18301886

18311887
/* --------------------------------
1832-
* RelationInitialize
1888+
* RelationCacheInitialize
18331889
*
18341890
* This initializes the relation descriptor cache.
18351891
* --------------------------------
@@ -1838,7 +1894,7 @@ RelationPurgeLocalRelation(bool xactCommitted)
18381894
#define INITRELCACHESIZE 400
18391895

18401896
void
1841-
RelationInitialize(void)
1897+
RelationCacheInitialize(void)
18421898
{
18431899
MemoryContext oldcxt;
18441900
HASHCTL ctl;
@@ -1870,6 +1926,8 @@ RelationInitialize(void)
18701926
* initialize the cache with pre-made relation descriptors
18711927
* for some of the more important system relations. These
18721928
* relations should always be in the cache.
1929+
*
1930+
* NB: see also the list in RelationCacheInitializePhase2().
18731931
* ----------------
18741932
*/
18751933
formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class);
@@ -1892,6 +1950,34 @@ RelationInitialize(void)
18921950
MemoryContextSwitchTo(oldcxt);
18931951
}
18941952

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+
18951981
static void
18961982
AttrDefaultFetch(Relation relation)
18971983
{

src/backend/utils/init/postinit.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.63 2000/07/08 03:04:16 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.64 2000/08/06 04:39:10 tgl Exp $
1212
*
1313
*
1414
*-------------------------------------------------------------------------
@@ -313,7 +313,8 @@ InitPostgres(const char *dbname)
313313
* it to examine AMI transaction status, and this is never written
314314
* after initdb is done. -mer 15 June 1992
315315
*/
316-
RelationInitialize(); /* pre-allocated reldescs created here */
316+
RelationCacheInitialize(); /* pre-allocated reldescs created here */
317+
317318
InitializeTransactionSystem(); /* pg_log,etc init/crash recovery
318319
* here */
319320

@@ -362,6 +363,9 @@ InitPostgres(const char *dbname)
362363
if (!bootstrap)
363364
StartTransactionCommand();
364365

366+
/* replace faked-up relcache entries with the real info */
367+
RelationCacheInitializePhase2();
368+
365369
/*
366370
* Set ourselves to the proper user id and figure out our postgres
367371
* user id. If we ever add security so that we check for valid

src/bin/initdb/initdb.sh

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#
2424
# Copyright (c) 1994, Regents of the University of California
2525
#
26-
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.101 2000/07/06 21:33:38 petere Exp $
26+
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.102 2000/08/06 04:39:22 tgl Exp $
2727
#
2828
#-------------------------------------------------------------------------
2929

@@ -519,9 +519,19 @@ if [ "$PwPrompt" ]; then
519519
fi
520520

521521

522-
echo "Enabling unlimited storage for pg_rewrite"
522+
echo "Enabling unlimited row width for system tables."
523+
echo "ALTER TABLE pg_attrdef CREATE TOAST TABLE" \
524+
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
525+
echo "ALTER TABLE pg_description CREATE TOAST TABLE" \
526+
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
527+
echo "ALTER TABLE pg_proc CREATE TOAST TABLE" \
528+
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
529+
echo "ALTER TABLE pg_relcheck CREATE TOAST TABLE" \
530+
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
523531
echo "ALTER TABLE pg_rewrite CREATE TOAST TABLE" \
524532
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
533+
echo "ALTER TABLE pg_statistic CREATE TOAST TABLE" \
534+
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
525535

526536

527537
echo "Creating view pg_user."

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy