Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * relcache.c
4 : * POSTGRES relation descriptor cache code
5 : *
6 : * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/utils/cache/relcache.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : /*
16 : * INTERFACE ROUTINES
17 : * RelationCacheInitialize - initialize relcache (to empty)
18 : * RelationCacheInitializePhase2 - initialize shared-catalog entries
19 : * RelationCacheInitializePhase3 - finish initializing relcache
20 : * RelationIdGetRelation - get a reldesc by relation id
21 : * RelationClose - close an open relation
22 : *
23 : * NOTES
24 : * The following code contains many undocumented hacks. Please be
25 : * careful....
26 : */
27 : #include "postgres.h"
28 :
29 : #include <sys/file.h>
30 : #include <fcntl.h>
31 : #include <unistd.h>
32 :
33 : #include "access/htup_details.h"
34 : #include "access/multixact.h"
35 : #include "access/nbtree.h"
36 : #include "access/parallel.h"
37 : #include "access/reloptions.h"
38 : #include "access/sysattr.h"
39 : #include "access/table.h"
40 : #include "access/tableam.h"
41 : #include "access/tupdesc_details.h"
42 : #include "access/xact.h"
43 : #include "access/xlog.h"
44 : #include "catalog/catalog.h"
45 : #include "catalog/index.h"
46 : #include "catalog/indexing.h"
47 : #include "catalog/namespace.h"
48 : #include "catalog/partition.h"
49 : #include "catalog/pg_am.h"
50 : #include "catalog/pg_amproc.h"
51 : #include "catalog/pg_attrdef.h"
52 : #include "catalog/pg_auth_members.h"
53 : #include "catalog/pg_authid.h"
54 : #include "catalog/pg_constraint.h"
55 : #include "catalog/pg_database.h"
56 : #include "catalog/pg_namespace.h"
57 : #include "catalog/pg_opclass.h"
58 : #include "catalog/pg_proc.h"
59 : #include "catalog/pg_publication.h"
60 : #include "catalog/pg_rewrite.h"
61 : #include "catalog/pg_shseclabel.h"
62 : #include "catalog/pg_statistic_ext.h"
63 : #include "catalog/pg_subscription.h"
64 : #include "catalog/pg_tablespace.h"
65 : #include "catalog/pg_trigger.h"
66 : #include "catalog/pg_type.h"
67 : #include "catalog/schemapg.h"
68 : #include "catalog/storage.h"
69 : #include "commands/policy.h"
70 : #include "commands/trigger.h"
71 : #include "miscadmin.h"
72 : #include "nodes/makefuncs.h"
73 : #include "nodes/nodeFuncs.h"
74 : #include "optimizer/optimizer.h"
75 : #include "rewrite/rewriteDefine.h"
76 : #include "rewrite/rowsecurity.h"
77 : #include "storage/lmgr.h"
78 : #include "storage/smgr.h"
79 : #include "utils/array.h"
80 : #include "utils/builtins.h"
81 : #include "utils/datum.h"
82 : #include "utils/fmgroids.h"
83 : #include "utils/inval.h"
84 : #include "utils/lsyscache.h"
85 : #include "utils/memutils.h"
86 : #include "utils/relmapper.h"
87 : #include "utils/resowner_private.h"
88 : #include "utils/snapmgr.h"
89 : #include "utils/syscache.h"
90 :
91 : #define RELCACHE_INIT_FILEMAGIC 0x573266 /* version ID value */
92 :
93 : /*
94 : * Whether to bother checking if relation cache memory needs to be freed
95 : * eagerly. See also RelationBuildDesc() and pg_config_manual.h.
96 : */
97 : #if defined(RECOVER_RELATION_BUILD_MEMORY) && (RECOVER_RELATION_BUILD_MEMORY != 0)
98 : #define MAYBE_RECOVER_RELATION_BUILD_MEMORY 1
99 : #else
100 : #define RECOVER_RELATION_BUILD_MEMORY 0
101 : #ifdef CLOBBER_CACHE_ENABLED
102 : #define MAYBE_RECOVER_RELATION_BUILD_MEMORY 1
103 : #endif
104 : #endif
105 :
106 : /*
107 : * hardcoded tuple descriptors, contents generated by genbki.pl
108 : */
109 : static const FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class};
110 : static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute};
111 : static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc};
112 : static const FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type};
113 : static const FormData_pg_attribute Desc_pg_database[Natts_pg_database] = {Schema_pg_database};
114 : static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid] = {Schema_pg_authid};
115 : static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members] = {Schema_pg_auth_members};
116 : static const FormData_pg_attribute Desc_pg_index[Natts_pg_index] = {Schema_pg_index};
117 : static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel] = {Schema_pg_shseclabel};
118 : static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription] = {Schema_pg_subscription};
119 :
120 : /*
121 : * Hash tables that index the relation cache
122 : *
123 : * We used to index the cache by both name and OID, but now there
124 : * is only an index by OID.
125 : */
126 : typedef struct relidcacheent
127 : {
128 : Oid reloid;
129 : Relation reldesc;
130 : } RelIdCacheEnt;
131 :
132 : static HTAB *RelationIdCache;
133 :
134 : /*
135 : * This flag is false until we have prepared the critical relcache entries
136 : * that are needed to do indexscans on the tables read by relcache building.
137 : */
138 : bool criticalRelcachesBuilt = false;
139 :
140 : /*
141 : * This flag is false until we have prepared the critical relcache entries
142 : * for shared catalogs (which are the tables needed for login).
143 : */
144 : bool criticalSharedRelcachesBuilt = false;
145 :
146 : /*
147 : * This counter counts relcache inval events received since backend startup
148 : * (but only for rels that are actually in cache). Presently, we use it only
149 : * to detect whether data about to be written by write_relcache_init_file()
150 : * might already be obsolete.
151 : */
152 : static long relcacheInvalsReceived = 0L;
153 :
154 : /*
155 : * eoxact_list[] stores the OIDs of relations that (might) need AtEOXact
156 : * cleanup work. This list intentionally has limited size; if it overflows,
157 : * we fall back to scanning the whole hashtable. There is no value in a very
158 : * large list because (1) at some point, a hash_seq_search scan is faster than
159 : * retail lookups, and (2) the value of this is to reduce EOXact work for
160 : * short transactions, which can't have dirtied all that many tables anyway.
161 : * EOXactListAdd() does not bother to prevent duplicate list entries, so the
162 : * cleanup processing must be idempotent.
163 : */
164 : #define MAX_EOXACT_LIST 32
165 : static Oid eoxact_list[MAX_EOXACT_LIST];
166 : static int eoxact_list_len = 0;
167 : static bool eoxact_list_overflowed = false;
168 :
169 : #define EOXactListAdd(rel) \
170 : do { \
171 : if (eoxact_list_len < MAX_EOXACT_LIST) \
172 : eoxact_list[eoxact_list_len++] = (rel)->rd_id; \
173 : else \
174 : eoxact_list_overflowed = true; \
175 : } while (0)
176 :
177 : /*
178 : * EOXactTupleDescArray stores TupleDescs that (might) need AtEOXact
179 : * cleanup work. The array expands as needed; there is no hashtable because
180 : * we don't need to access individual items except at EOXact.
181 : */
182 : static TupleDesc *EOXactTupleDescArray;
183 : static int NextEOXactTupleDescNum = 0;
184 : static int EOXactTupleDescArrayLen = 0;
185 :
186 : /*
187 : * macros to manipulate the lookup hashtable
188 : */
189 : #define RelationCacheInsert(RELATION, replace_allowed) \
190 : do { \
191 : RelIdCacheEnt *hentry; bool found; \
192 : hentry = (RelIdCacheEnt *) hash_search(RelationIdCache, \
193 : (void *) &((RELATION)->rd_id), \
194 : HASH_ENTER, &found); \
195 : if (found) \
196 : { \
197 : /* see comments in RelationBuildDesc and RelationBuildLocalRelation */ \
198 : Relation _old_rel = hentry->reldesc; \
199 : Assert(replace_allowed); \
200 : hentry->reldesc = (RELATION); \
201 : if (RelationHasReferenceCountZero(_old_rel)) \
202 : RelationDestroyRelation(_old_rel, false); \
203 : else if (!IsBootstrapProcessingMode()) \
204 : elog(WARNING, "leaking still-referenced relcache entry for \"%s\"", \
205 : RelationGetRelationName(_old_rel)); \
206 : } \
207 : else \
208 : hentry->reldesc = (RELATION); \
209 : } while(0)
210 :
211 : #define RelationIdCacheLookup(ID, RELATION) \
212 : do { \
213 : RelIdCacheEnt *hentry; \
214 : hentry = (RelIdCacheEnt *) hash_search(RelationIdCache, \
215 : (void *) &(ID), \
216 : HASH_FIND, NULL); \
217 : if (hentry) \
218 : RELATION = hentry->reldesc; \
219 : else \
220 : RELATION = NULL; \
221 : } while(0)
222 :
223 : #define RelationCacheDelete(RELATION) \
224 : do { \
225 : RelIdCacheEnt *hentry; \
226 : hentry = (RelIdCacheEnt *) hash_search(RelationIdCache, \
227 : (void *) &((RELATION)->rd_id), \
228 : HASH_REMOVE, NULL); \
229 : if (hentry == NULL) \
230 : elog(WARNING, "failed to delete relcache entry for OID %u", \
231 : (RELATION)->rd_id); \
232 : } while(0)
233 :
234 :
235 : /*
236 : * Special cache for opclass-related information
237 : *
238 : * Note: only default support procs get cached, ie, those with
239 : * lefttype = righttype = opcintype.
240 : */
241 : typedef struct opclasscacheent
242 : {
243 : Oid opclassoid; /* lookup key: OID of opclass */
244 : bool valid; /* set true after successful fill-in */
245 : StrategyNumber numSupport; /* max # of support procs (from pg_am) */
246 : Oid opcfamily; /* OID of opclass's family */
247 : Oid opcintype; /* OID of opclass's declared input type */
248 : RegProcedure *supportProcs; /* OIDs of support procedures */
249 : } OpClassCacheEnt;
250 :
251 : static HTAB *OpClassCache = NULL;
252 :
253 :
254 : /* non-export function prototypes */
255 :
256 : static void RelationDestroyRelation(Relation relation, bool remember_tupdesc);
257 : static void RelationClearRelation(Relation relation, bool rebuild);
258 :
259 : static void RelationReloadIndexInfo(Relation relation);
260 : static void RelationReloadNailed(Relation relation);
261 : static void RelationFlushRelation(Relation relation);
262 : static void RememberToFreeTupleDescAtEOX(TupleDesc td);
263 : #ifdef USE_ASSERT_CHECKING
264 : static void AssertPendingSyncConsistency(Relation relation);
265 : #endif
266 : static void AtEOXact_cleanup(Relation relation, bool isCommit);
267 : static void AtEOSubXact_cleanup(Relation relation, bool isCommit,
268 : SubTransactionId mySubid, SubTransactionId parentSubid);
269 : static bool load_relcache_init_file(bool shared);
270 : static void write_relcache_init_file(bool shared);
271 : static void write_item(const void *data, Size len, FILE *fp);
272 :
273 : static void formrdesc(const char *relationName, Oid relationReltype,
274 : bool isshared, int natts, const FormData_pg_attribute *attrs);
275 :
276 : static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic);
277 : static Relation AllocateRelationDesc(Form_pg_class relp);
278 : static void RelationParseRelOptions(Relation relation, HeapTuple tuple);
279 : static void RelationBuildTupleDesc(Relation relation);
280 : static Relation RelationBuildDesc(Oid targetRelId, bool insertIt);
281 : static void RelationInitPhysicalAddr(Relation relation);
282 : static void load_critical_index(Oid indexoid, Oid heapoid);
283 : static TupleDesc GetPgClassDescriptor(void);
284 : static TupleDesc GetPgIndexDescriptor(void);
285 : static void AttrDefaultFetch(Relation relation);
286 : static void CheckConstraintFetch(Relation relation);
287 : static int CheckConstraintCmp(const void *a, const void *b);
288 : static void InitIndexAmRoutine(Relation relation);
289 : static void IndexSupportInitialize(oidvector *indclass,
290 : RegProcedure *indexSupport,
291 : Oid *opFamily,
292 : Oid *opcInType,
293 : StrategyNumber maxSupportNumber,
294 : AttrNumber maxAttributeNumber);
295 : static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid,
296 : StrategyNumber numSupport);
297 : static void RelationCacheInitFileRemoveInDir(const char *tblspcpath);
298 : static void unlink_initfile(const char *initfilename, int elevel);
299 :
300 :
301 : /*
302 : * ScanPgRelation
303 : *
304 : * This is used by RelationBuildDesc to find a pg_class
305 : * tuple matching targetRelId. The caller must hold at least
306 : * AccessShareLock on the target relid to prevent concurrent-update
307 : * scenarios; it isn't guaranteed that all scans used to build the
308 : * relcache entry will use the same snapshot. If, for example,
309 : * an attribute were to be added after scanning pg_class and before
310 : * scanning pg_attribute, relnatts wouldn't match.
311 : *
312 : * NB: the returned tuple has been copied into palloc'd storage
313 : * and must eventually be freed with heap_freetuple.
314 : */
315 : static HeapTuple
316 952928 : ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic)
317 : {
318 : HeapTuple pg_class_tuple;
319 : Relation pg_class_desc;
320 : SysScanDesc pg_class_scan;
321 : ScanKeyData key[1];
322 952928 : Snapshot snapshot = NULL;
323 :
324 : /*
325 : * If something goes wrong during backend startup, we might find ourselves
326 : * trying to read pg_class before we've selected a database. That ain't
327 : * gonna work, so bail out with a useful error message. If this happens,
328 : * it probably means a relcache entry that needs to be nailed isn't.
329 : */
330 952928 : if (!OidIsValid(MyDatabaseId))
331 0 : elog(FATAL, "cannot read pg_class without having selected a database");
332 :
333 : /*
334 : * form a scan key
335 : */
336 952928 : ScanKeyInit(&key[0],
337 : Anum_pg_class_oid,
338 : BTEqualStrategyNumber, F_OIDEQ,
339 : ObjectIdGetDatum(targetRelId));
340 :
341 : /*
342 : * Open pg_class and fetch a tuple. Force heap scan if we haven't yet
343 : * built the critical relcache entries (this includes initdb and startup
344 : * without a pg_internal.init file). The caller can also force a heap
345 : * scan by setting indexOK == false.
346 : */
347 952928 : pg_class_desc = table_open(RelationRelationId, AccessShareLock);
348 :
349 : /*
350 : * The caller might need a tuple that's newer than the one the historic
351 : * snapshot; currently the only case requiring to do so is looking up the
352 : * relfilenode of non mapped system relations during decoding. That
353 : * snapshot can't change in the midst of a relcache build, so there's no
354 : * need to register the snapshot.
355 : */
356 952928 : if (force_non_historic)
357 1808 : snapshot = GetNonHistoricCatalogSnapshot(RelationRelationId);
358 :
359 952928 : pg_class_scan = systable_beginscan(pg_class_desc, ClassOidIndexId,
360 952928 : indexOK && criticalRelcachesBuilt,
361 : snapshot,
362 : 1, key);
363 :
364 952922 : pg_class_tuple = systable_getnext(pg_class_scan);
365 :
366 : /*
367 : * Must copy tuple before releasing buffer.
368 : */
369 952916 : if (HeapTupleIsValid(pg_class_tuple))
370 952908 : pg_class_tuple = heap_copytuple(pg_class_tuple);
371 :
372 : /* all done */
373 952916 : systable_endscan(pg_class_scan);
374 952916 : table_close(pg_class_desc, AccessShareLock);
375 :
376 952916 : return pg_class_tuple;
377 : }
378 :
379 : /*
380 : * AllocateRelationDesc
381 : *
382 : * This is used to allocate memory for a new relation descriptor
383 : * and initialize the rd_rel field from the given pg_class tuple.
384 : */
385 : static Relation
386 881526 : AllocateRelationDesc(Form_pg_class relp)
387 : {
388 : Relation relation;
389 : MemoryContext oldcxt;
390 : Form_pg_class relationForm;
391 :
392 : /* Relcache entries must live in CacheMemoryContext */
393 881526 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
394 :
395 : /*
396 : * allocate and zero space for new relation descriptor
397 : */
398 881526 : relation = (Relation) palloc0(sizeof(RelationData));
399 :
400 : /* make sure relation is marked as having no open file yet */
401 881526 : relation->rd_smgr = NULL;
402 :
403 : /*
404 : * Copy the relation tuple form
405 : *
406 : * We only allocate space for the fixed fields, ie, CLASS_TUPLE_SIZE. The
407 : * variable-length fields (relacl, reloptions) are NOT stored in the
408 : * relcache --- there'd be little point in it, since we don't copy the
409 : * tuple's nulls bitmap and hence wouldn't know if the values are valid.
410 : * Bottom line is that relacl *cannot* be retrieved from the relcache. Get
411 : * it from the syscache if you need it. The same goes for the original
412 : * form of reloptions (however, we do store the parsed form of reloptions
413 : * in rd_options).
414 : */
415 881526 : relationForm = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
416 :
417 881526 : memcpy(relationForm, relp, CLASS_TUPLE_SIZE);
418 :
419 : /* initialize relation tuple form */
420 881526 : relation->rd_rel = relationForm;
421 :
422 : /* and allocate attribute tuple form storage */
423 881526 : relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts);
424 : /* which we mark as a reference-counted tupdesc */
425 881526 : relation->rd_att->tdrefcount = 1;
426 :
427 881526 : MemoryContextSwitchTo(oldcxt);
428 :
429 881526 : return relation;
430 : }
431 :
432 : /*
433 : * RelationParseRelOptions
434 : * Convert pg_class.reloptions into pre-parsed rd_options
435 : *
436 : * tuple is the real pg_class tuple (not rd_rel!) for relation
437 : *
438 : * Note: rd_rel and (if an index) rd_indam must be valid already
439 : */
440 : static void
441 943678 : RelationParseRelOptions(Relation relation, HeapTuple tuple)
442 : {
443 : bytea *options;
444 : amoptions_function amoptsfn;
445 :
446 943678 : relation->rd_options = NULL;
447 :
448 : /*
449 : * Look up any AM-specific parse function; fall out if relkind should not
450 : * have options.
451 : */
452 943678 : switch (relation->rd_rel->relkind)
453 : {
454 599788 : case RELKIND_RELATION:
455 : case RELKIND_TOASTVALUE:
456 : case RELKIND_VIEW:
457 : case RELKIND_MATVIEW:
458 : case RELKIND_PARTITIONED_TABLE:
459 599788 : amoptsfn = NULL;
460 599788 : break;
461 338264 : case RELKIND_INDEX:
462 : case RELKIND_PARTITIONED_INDEX:
463 338264 : amoptsfn = relation->rd_indam->amoptions;
464 338264 : break;
465 5626 : default:
466 5626 : return;
467 : }
468 :
469 : /*
470 : * Fetch reloptions from tuple; have to use a hardwired descriptor because
471 : * we might not have any other for pg_class yet (consider executing this
472 : * code for pg_class itself)
473 : */
474 938052 : options = extractRelOptions(tuple, GetPgClassDescriptor(), amoptsfn);
475 :
476 : /*
477 : * Copy parsed data into CacheMemoryContext. To guard against the
478 : * possibility of leaks in the reloptions code, we want to do the actual
479 : * parsing in the caller's memory context and copy the results into
480 : * CacheMemoryContext after the fact.
481 : */
482 938052 : if (options)
483 : {
484 16640 : relation->rd_options = MemoryContextAlloc(CacheMemoryContext,
485 8320 : VARSIZE(options));
486 8320 : memcpy(relation->rd_options, options, VARSIZE(options));
487 8320 : pfree(options);
488 : }
489 : }
490 :
491 : /*
492 : * RelationBuildTupleDesc
493 : *
494 : * Form the relation's tuple descriptor from information in
495 : * the pg_attribute, pg_attrdef & pg_constraint system catalogs.
496 : */
497 : static void
498 881526 : RelationBuildTupleDesc(Relation relation)
499 : {
500 : HeapTuple pg_attribute_tuple;
501 : Relation pg_attribute_desc;
502 : SysScanDesc pg_attribute_scan;
503 : ScanKeyData skey[2];
504 : int need;
505 : TupleConstr *constr;
506 881526 : AttrDefault *attrdef = NULL;
507 881526 : AttrMissing *attrmiss = NULL;
508 881526 : int ndef = 0;
509 :
510 : /* fill rd_att's type ID fields (compare heap.c's AddNewRelationTuple) */
511 881526 : relation->rd_att->tdtypeid =
512 881526 : relation->rd_rel->reltype ? relation->rd_rel->reltype : RECORDOID;
513 881526 : relation->rd_att->tdtypmod = -1; /* just to be sure */
514 :
515 881526 : constr = (TupleConstr *) MemoryContextAlloc(CacheMemoryContext,
516 : sizeof(TupleConstr));
517 881526 : constr->has_not_null = false;
518 881526 : constr->has_generated_stored = false;
519 :
520 : /*
521 : * Form a scan key that selects only user attributes (attnum > 0).
522 : * (Eliminating system attribute rows at the index level is lots faster
523 : * than fetching them.)
524 : */
525 881526 : ScanKeyInit(&skey[0],
526 : Anum_pg_attribute_attrelid,
527 : BTEqualStrategyNumber, F_OIDEQ,
528 881526 : ObjectIdGetDatum(RelationGetRelid(relation)));
529 881526 : ScanKeyInit(&skey[1],
530 : Anum_pg_attribute_attnum,
531 : BTGreaterStrategyNumber, F_INT2GT,
532 : Int16GetDatum(0));
533 :
534 : /*
535 : * Open pg_attribute and begin a scan. Force heap scan if we haven't yet
536 : * built the critical relcache entries (this includes initdb and startup
537 : * without a pg_internal.init file).
538 : */
539 881526 : pg_attribute_desc = table_open(AttributeRelationId, AccessShareLock);
540 881526 : pg_attribute_scan = systable_beginscan(pg_attribute_desc,
541 : AttributeRelidNumIndexId,
542 : criticalRelcachesBuilt,
543 : NULL,
544 : 2, skey);
545 :
546 : /*
547 : * add attribute data to relation->rd_att
548 : */
549 881526 : need = RelationGetNumberOfAttributes(relation);
550 :
551 4151286 : while (HeapTupleIsValid(pg_attribute_tuple = systable_getnext(pg_attribute_scan)))
552 : {
553 : Form_pg_attribute attp;
554 : int attnum;
555 :
556 4150638 : attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
557 :
558 4150638 : attnum = attp->attnum;
559 4150638 : if (attnum <= 0 || attnum > RelationGetNumberOfAttributes(relation))
560 0 : elog(ERROR, "invalid attribute number %d for %s",
561 : attp->attnum, RelationGetRelationName(relation));
562 :
563 :
564 4150638 : memcpy(TupleDescAttr(relation->rd_att, attnum - 1),
565 : attp,
566 : ATTRIBUTE_FIXED_PART_SIZE);
567 :
568 : /* Update constraint/default info */
569 4150638 : if (attp->attnotnull)
570 1557810 : constr->has_not_null = true;
571 4150638 : if (attp->attgenerated == ATTRIBUTE_GENERATED_STORED)
572 2196 : constr->has_generated_stored = true;
573 :
574 : /* If the column has a default, fill it into the attrdef array */
575 4150638 : if (attp->atthasdef)
576 : {
577 19964 : if (attrdef == NULL)
578 : attrdef = (AttrDefault *)
579 13850 : MemoryContextAllocZero(CacheMemoryContext,
580 13850 : RelationGetNumberOfAttributes(relation) *
581 : sizeof(AttrDefault));
582 19964 : attrdef[ndef].adnum = attnum;
583 19964 : attrdef[ndef].adbin = NULL;
584 :
585 19964 : ndef++;
586 : }
587 :
588 : /* Likewise for a missing value */
589 4150638 : if (attp->atthasmissing)
590 : {
591 : Datum missingval;
592 : bool missingNull;
593 :
594 : /* Do we have a missing value? */
595 5186 : missingval = heap_getattr(pg_attribute_tuple,
596 : Anum_pg_attribute_attmissingval,
597 : pg_attribute_desc->rd_att,
598 : &missingNull);
599 5186 : if (!missingNull)
600 : {
601 : /* Yes, fetch from the array */
602 : MemoryContext oldcxt;
603 : bool is_null;
604 5186 : int one = 1;
605 : Datum missval;
606 :
607 5186 : if (attrmiss == NULL)
608 : attrmiss = (AttrMissing *)
609 2664 : MemoryContextAllocZero(CacheMemoryContext,
610 2664 : relation->rd_rel->relnatts *
611 : sizeof(AttrMissing));
612 :
613 15558 : missval = array_get_element(missingval,
614 : 1,
615 : &one,
616 : -1,
617 5186 : attp->attlen,
618 5186 : attp->attbyval,
619 5186 : attp->attalign,
620 : &is_null);
621 : Assert(!is_null);
622 5186 : if (attp->attbyval)
623 : {
624 : /* for copy by val just copy the datum direct */
625 3528 : attrmiss[attnum - 1].am_value = missval;
626 : }
627 : else
628 : {
629 : /* otherwise copy in the correct context */
630 1658 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
631 4974 : attrmiss[attnum - 1].am_value = datumCopy(missval,
632 1658 : attp->attbyval,
633 1658 : attp->attlen);
634 1658 : MemoryContextSwitchTo(oldcxt);
635 : }
636 5186 : attrmiss[attnum - 1].am_present = true;
637 : }
638 : }
639 4150638 : need--;
640 4150638 : if (need == 0)
641 880878 : break;
642 : }
643 :
644 : /*
645 : * end the scan and close the attribute relation
646 : */
647 881526 : systable_endscan(pg_attribute_scan);
648 881526 : table_close(pg_attribute_desc, AccessShareLock);
649 :
650 881526 : if (need != 0)
651 0 : elog(ERROR, "catalog is missing %d attribute(s) for relid %u",
652 : need, RelationGetRelid(relation));
653 :
654 : /*
655 : * The attcacheoff values we read from pg_attribute should all be -1
656 : * ("unknown"). Verify this if assert checking is on. They will be
657 : * computed when and if needed during tuple access.
658 : */
659 : #ifdef USE_ASSERT_CHECKING
660 : {
661 : int i;
662 :
663 : for (i = 0; i < RelationGetNumberOfAttributes(relation); i++)
664 : Assert(TupleDescAttr(relation->rd_att, i)->attcacheoff == -1);
665 : }
666 : #endif
667 :
668 : /*
669 : * However, we can easily set the attcacheoff value for the first
670 : * attribute: it must be zero. This eliminates the need for special cases
671 : * for attnum=1 that used to exist in fastgetattr() and index_getattr().
672 : */
673 881526 : if (RelationGetNumberOfAttributes(relation) > 0)
674 880878 : TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
675 :
676 : /*
677 : * Set up constraint/default info
678 : */
679 881526 : if (constr->has_not_null ||
680 601698 : constr->has_generated_stored ||
681 598450 : ndef > 0 ||
682 598434 : attrmiss ||
683 598434 : relation->rd_rel->relchecks)
684 : {
685 285558 : relation->rd_att->constr = constr;
686 :
687 285558 : if (ndef > 0) /* DEFAULTs */
688 : {
689 13850 : if (ndef < RelationGetNumberOfAttributes(relation))
690 11694 : constr->defval = (AttrDefault *)
691 11694 : repalloc(attrdef, ndef * sizeof(AttrDefault));
692 : else
693 2156 : constr->defval = attrdef;
694 13850 : constr->num_defval = ndef;
695 13850 : AttrDefaultFetch(relation);
696 : }
697 : else
698 271708 : constr->num_defval = 0;
699 :
700 285558 : constr->missing = attrmiss;
701 :
702 571116 : if (relation->rd_rel->relchecks > 0) /* CHECKs */
703 : {
704 5640 : constr->num_check = relation->rd_rel->relchecks;
705 5640 : constr->check = (ConstrCheck *)
706 5640 : MemoryContextAllocZero(CacheMemoryContext,
707 5640 : constr->num_check * sizeof(ConstrCheck));
708 5640 : CheckConstraintFetch(relation);
709 : }
710 : else
711 279918 : constr->num_check = 0;
712 : }
713 : else
714 : {
715 595968 : pfree(constr);
716 595968 : relation->rd_att->constr = NULL;
717 : }
718 881526 : }
719 :
720 : /*
721 : * RelationBuildRuleLock
722 : *
723 : * Form the relation's rewrite rules from information in
724 : * the pg_rewrite system catalog.
725 : *
726 : * Note: The rule parsetrees are potentially very complex node structures.
727 : * To allow these trees to be freed when the relcache entry is flushed,
728 : * we make a private memory context to hold the RuleLock information for
729 : * each relcache entry that has associated rules. The context is used
730 : * just for rule info, not for any other subsidiary data of the relcache
731 : * entry, because that keeps the update logic in RelationClearRelation()
732 : * manageable. The other subsidiary data structures are simple enough
733 : * to be easy to free explicitly, anyway.
734 : */
735 : static void
736 74462 : RelationBuildRuleLock(Relation relation)
737 : {
738 : MemoryContext rulescxt;
739 : MemoryContext oldcxt;
740 : HeapTuple rewrite_tuple;
741 : Relation rewrite_desc;
742 : TupleDesc rewrite_tupdesc;
743 : SysScanDesc rewrite_scan;
744 : ScanKeyData key;
745 : RuleLock *rulelock;
746 : int numlocks;
747 : RewriteRule **rules;
748 : int maxlocks;
749 :
750 : /*
751 : * Make the private context. Assume it'll not contain much data.
752 : */
753 74462 : rulescxt = AllocSetContextCreate(CacheMemoryContext,
754 : "relation rules",
755 : ALLOCSET_SMALL_SIZES);
756 74462 : relation->rd_rulescxt = rulescxt;
757 74462 : MemoryContextCopyAndSetIdentifier(rulescxt,
758 : RelationGetRelationName(relation));
759 :
760 : /*
761 : * allocate an array to hold the rewrite rules (the array is extended if
762 : * necessary)
763 : */
764 74462 : maxlocks = 4;
765 : rules = (RewriteRule **)
766 74462 : MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks);
767 74462 : numlocks = 0;
768 :
769 : /*
770 : * form a scan key
771 : */
772 74462 : ScanKeyInit(&key,
773 : Anum_pg_rewrite_ev_class,
774 : BTEqualStrategyNumber, F_OIDEQ,
775 74462 : ObjectIdGetDatum(RelationGetRelid(relation)));
776 :
777 : /*
778 : * open pg_rewrite and begin a scan
779 : *
780 : * Note: since we scan the rules using RewriteRelRulenameIndexId, we will
781 : * be reading the rules in name order, except possibly during
782 : * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
783 : * ensures that rules will be fired in name order.
784 : */
785 74462 : rewrite_desc = table_open(RewriteRelationId, AccessShareLock);
786 74462 : rewrite_tupdesc = RelationGetDescr(rewrite_desc);
787 74462 : rewrite_scan = systable_beginscan(rewrite_desc,
788 : RewriteRelRulenameIndexId,
789 : true, NULL,
790 : 1, &key);
791 :
792 148420 : while (HeapTupleIsValid(rewrite_tuple = systable_getnext(rewrite_scan)))
793 : {
794 73958 : Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple);
795 : bool isnull;
796 : Datum rule_datum;
797 : char *rule_str;
798 : RewriteRule *rule;
799 :
800 73958 : rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
801 : sizeof(RewriteRule));
802 :
803 73958 : rule->ruleId = rewrite_form->oid;
804 :
805 73958 : rule->event = rewrite_form->ev_type - '0';
806 73958 : rule->enabled = rewrite_form->ev_enabled;
807 73958 : rule->isInstead = rewrite_form->is_instead;
808 :
809 : /*
810 : * Must use heap_getattr to fetch ev_action and ev_qual. Also, the
811 : * rule strings are often large enough to be toasted. To avoid
812 : * leaking memory in the caller's context, do the detoasting here so
813 : * we can free the detoasted version.
814 : */
815 73958 : rule_datum = heap_getattr(rewrite_tuple,
816 : Anum_pg_rewrite_ev_action,
817 : rewrite_tupdesc,
818 : &isnull);
819 : Assert(!isnull);
820 73958 : rule_str = TextDatumGetCString(rule_datum);
821 73958 : oldcxt = MemoryContextSwitchTo(rulescxt);
822 73958 : rule->actions = (List *) stringToNode(rule_str);
823 73958 : MemoryContextSwitchTo(oldcxt);
824 73958 : pfree(rule_str);
825 :
826 73958 : rule_datum = heap_getattr(rewrite_tuple,
827 : Anum_pg_rewrite_ev_qual,
828 : rewrite_tupdesc,
829 : &isnull);
830 : Assert(!isnull);
831 73958 : rule_str = TextDatumGetCString(rule_datum);
832 73958 : oldcxt = MemoryContextSwitchTo(rulescxt);
833 73958 : rule->qual = (Node *) stringToNode(rule_str);
834 73958 : MemoryContextSwitchTo(oldcxt);
835 73958 : pfree(rule_str);
836 :
837 : /*
838 : * We want the rule's table references to be checked as though by the
839 : * table owner, not the user referencing the rule. Therefore, scan
840 : * through the rule's actions and set the checkAsUser field on all
841 : * rtable entries. We have to look at the qual as well, in case it
842 : * contains sublinks.
843 : *
844 : * The reason for doing this when the rule is loaded, rather than when
845 : * it is stored, is that otherwise ALTER TABLE OWNER would have to
846 : * grovel through stored rules to update checkAsUser fields. Scanning
847 : * the rule tree during load is relatively cheap (compared to
848 : * constructing it in the first place), so we do it here.
849 : */
850 73958 : setRuleCheckAsUser((Node *) rule->actions, relation->rd_rel->relowner);
851 73958 : setRuleCheckAsUser(rule->qual, relation->rd_rel->relowner);
852 :
853 73958 : if (numlocks >= maxlocks)
854 : {
855 10 : maxlocks *= 2;
856 : rules = (RewriteRule **)
857 10 : repalloc(rules, sizeof(RewriteRule *) * maxlocks);
858 : }
859 73958 : rules[numlocks++] = rule;
860 : }
861 :
862 : /*
863 : * end the scan and close the attribute relation
864 : */
865 74462 : systable_endscan(rewrite_scan);
866 74462 : table_close(rewrite_desc, AccessShareLock);
867 :
868 : /*
869 : * there might not be any rules (if relhasrules is out-of-date)
870 : */
871 74462 : if (numlocks == 0)
872 : {
873 1550 : relation->rd_rules = NULL;
874 1550 : relation->rd_rulescxt = NULL;
875 1550 : MemoryContextDelete(rulescxt);
876 1550 : return;
877 : }
878 :
879 : /*
880 : * form a RuleLock and insert into relation
881 : */
882 72912 : rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock));
883 72912 : rulelock->numLocks = numlocks;
884 72912 : rulelock->rules = rules;
885 :
886 72912 : relation->rd_rules = rulelock;
887 : }
888 :
889 : /*
890 : * equalRuleLocks
891 : *
892 : * Determine whether two RuleLocks are equivalent
893 : *
894 : * Probably this should be in the rules code someplace...
895 : */
896 : static bool
897 324340 : equalRuleLocks(RuleLock *rlock1, RuleLock *rlock2)
898 : {
899 : int i;
900 :
901 : /*
902 : * As of 7.3 we assume the rule ordering is repeatable, because
903 : * RelationBuildRuleLock should read 'em in a consistent order. So just
904 : * compare corresponding slots.
905 : */
906 324340 : if (rlock1 != NULL)
907 : {
908 930 : if (rlock2 == NULL)
909 8 : return false;
910 922 : if (rlock1->numLocks != rlock2->numLocks)
911 0 : return false;
912 1714 : for (i = 0; i < rlock1->numLocks; i++)
913 : {
914 930 : RewriteRule *rule1 = rlock1->rules[i];
915 930 : RewriteRule *rule2 = rlock2->rules[i];
916 :
917 930 : if (rule1->ruleId != rule2->ruleId)
918 0 : return false;
919 930 : if (rule1->event != rule2->event)
920 0 : return false;
921 930 : if (rule1->enabled != rule2->enabled)
922 12 : return false;
923 918 : if (rule1->isInstead != rule2->isInstead)
924 0 : return false;
925 918 : if (!equal(rule1->qual, rule2->qual))
926 0 : return false;
927 918 : if (!equal(rule1->actions, rule2->actions))
928 126 : return false;
929 : }
930 : }
931 323410 : else if (rlock2 != NULL)
932 54972 : return false;
933 269222 : return true;
934 : }
935 :
936 : /*
937 : * equalPolicy
938 : *
939 : * Determine whether two policies are equivalent
940 : */
941 : static bool
942 132 : equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
943 : {
944 : int i;
945 : Oid *r1,
946 : *r2;
947 :
948 132 : if (policy1 != NULL)
949 : {
950 132 : if (policy2 == NULL)
951 0 : return false;
952 :
953 132 : if (policy1->polcmd != policy2->polcmd)
954 0 : return false;
955 132 : if (policy1->hassublinks != policy2->hassublinks)
956 0 : return false;
957 132 : if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
958 0 : return false;
959 132 : if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
960 0 : return false;
961 :
962 132 : r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
963 132 : r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
964 :
965 264 : for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
966 : {
967 132 : if (r1[i] != r2[i])
968 0 : return false;
969 : }
970 :
971 132 : if (!equal(policy1->qual, policy2->qual))
972 0 : return false;
973 132 : if (!equal(policy1->with_check_qual, policy2->with_check_qual))
974 0 : return false;
975 : }
976 0 : else if (policy2 != NULL)
977 0 : return false;
978 :
979 132 : return true;
980 : }
981 :
982 : /*
983 : * equalRSDesc
984 : *
985 : * Determine whether two RowSecurityDesc's are equivalent
986 : */
987 : static bool
988 324340 : equalRSDesc(RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2)
989 : {
990 : ListCell *lc,
991 : *rc;
992 :
993 324340 : if (rsdesc1 == NULL && rsdesc2 == NULL)
994 324074 : return true;
995 :
996 266 : if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
997 182 : (rsdesc1 == NULL && rsdesc2 != NULL))
998 190 : return false;
999 :
1000 76 : if (list_length(rsdesc1->policies) != list_length(rsdesc2->policies))
1001 0 : return false;
1002 :
1003 : /* RelationBuildRowSecurity should build policies in order */
1004 208 : forboth(lc, rsdesc1->policies, rc, rsdesc2->policies)
1005 : {
1006 132 : RowSecurityPolicy *l = (RowSecurityPolicy *) lfirst(lc);
1007 132 : RowSecurityPolicy *r = (RowSecurityPolicy *) lfirst(rc);
1008 :
1009 132 : if (!equalPolicy(l, r))
1010 0 : return false;
1011 : }
1012 :
1013 76 : return true;
1014 : }
1015 :
1016 : /*
1017 : * RelationBuildDesc
1018 : *
1019 : * Build a relation descriptor. The caller must hold at least
1020 : * AccessShareLock on the target relid.
1021 : *
1022 : * The new descriptor is inserted into the hash table if insertIt is true.
1023 : *
1024 : * Returns NULL if no pg_class row could be found for the given relid
1025 : * (suggesting we are trying to access a just-deleted relation).
1026 : * Any other error is reported via elog.
1027 : */
1028 : static Relation
1029 881534 : RelationBuildDesc(Oid targetRelId, bool insertIt)
1030 : {
1031 : Relation relation;
1032 : Oid relid;
1033 : HeapTuple pg_class_tuple;
1034 : Form_pg_class relp;
1035 :
1036 : /*
1037 : * This function and its subroutines can allocate a good deal of transient
1038 : * data in CurrentMemoryContext. Traditionally we've just leaked that
1039 : * data, reasoning that the caller's context is at worst of transaction
1040 : * scope, and relcache loads shouldn't happen so often that it's essential
1041 : * to recover transient data before end of statement/transaction. However
1042 : * that's definitely not true in clobber-cache test builds, and perhaps
1043 : * it's not true in other cases.
1044 : *
1045 : * When cache clobbering is enabled or when forced to by
1046 : * RECOVER_RELATION_BUILD_MEMORY=1, arrange to allocate the junk in a
1047 : * temporary context that we'll free before returning. Make it a child
1048 : * of caller's context so that it will get cleaned up appropriately if
1049 : * we error out partway through.
1050 : */
1051 : #ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1052 : MemoryContext tmpcxt = NULL;
1053 : MemoryContext oldcxt = NULL;
1054 :
1055 : if (RECOVER_RELATION_BUILD_MEMORY || debug_invalidate_system_caches_always > 0)
1056 : {
1057 : tmpcxt = AllocSetContextCreate(CurrentMemoryContext,
1058 : "RelationBuildDesc workspace",
1059 : ALLOCSET_DEFAULT_SIZES);
1060 : oldcxt = MemoryContextSwitchTo(tmpcxt);
1061 : }
1062 : #endif
1063 :
1064 : /*
1065 : * find the tuple in pg_class corresponding to the given relation id
1066 : */
1067 881534 : pg_class_tuple = ScanPgRelation(targetRelId, true, false);
1068 :
1069 : /*
1070 : * if no such tuple exists, return NULL
1071 : */
1072 881534 : if (!HeapTupleIsValid(pg_class_tuple))
1073 : {
1074 : #ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1075 : if (tmpcxt)
1076 : {
1077 : /* Return to caller's context, and blow away the temporary context */
1078 : MemoryContextSwitchTo(oldcxt);
1079 : MemoryContextDelete(tmpcxt);
1080 : }
1081 : #endif
1082 8 : return NULL;
1083 : }
1084 :
1085 : /*
1086 : * get information from the pg_class_tuple
1087 : */
1088 881526 : relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
1089 881526 : relid = relp->oid;
1090 : Assert(relid == targetRelId);
1091 :
1092 : /*
1093 : * allocate storage for the relation descriptor, and copy pg_class_tuple
1094 : * to relation->rd_rel.
1095 : */
1096 881526 : relation = AllocateRelationDesc(relp);
1097 :
1098 : /*
1099 : * initialize the relation's relation id (relation->rd_id)
1100 : */
1101 881526 : RelationGetRelid(relation) = relid;
1102 :
1103 : /*
1104 : * Normal relations are not nailed into the cache. Since we don't flush
1105 : * new relations, it won't be new. It could be temp though.
1106 : */
1107 881526 : relation->rd_refcnt = 0;
1108 881526 : relation->rd_isnailed = false;
1109 881526 : relation->rd_createSubid = InvalidSubTransactionId;
1110 881526 : relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
1111 881526 : relation->rd_firstRelfilenodeSubid = InvalidSubTransactionId;
1112 881526 : relation->rd_droppedSubid = InvalidSubTransactionId;
1113 881526 : switch (relation->rd_rel->relpersistence)
1114 : {
1115 867322 : case RELPERSISTENCE_UNLOGGED:
1116 : case RELPERSISTENCE_PERMANENT:
1117 867322 : relation->rd_backend = InvalidBackendId;
1118 867322 : relation->rd_islocaltemp = false;
1119 867322 : break;
1120 14204 : case RELPERSISTENCE_TEMP:
1121 14204 : if (isTempOrTempToastNamespace(relation->rd_rel->relnamespace))
1122 : {
1123 14170 : relation->rd_backend = BackendIdForTempRelations();
1124 14170 : relation->rd_islocaltemp = true;
1125 : }
1126 : else
1127 : {
1128 : /*
1129 : * If it's a temp table, but not one of ours, we have to use
1130 : * the slow, grotty method to figure out the owning backend.
1131 : *
1132 : * Note: it's possible that rd_backend gets set to MyBackendId
1133 : * here, in case we are looking at a pg_class entry left over
1134 : * from a crashed backend that coincidentally had the same
1135 : * BackendId we're using. We should *not* consider such a
1136 : * table to be "ours"; this is why we need the separate
1137 : * rd_islocaltemp flag. The pg_class entry will get flushed
1138 : * if/when we clean out the corresponding temp table namespace
1139 : * in preparation for using it.
1140 : */
1141 34 : relation->rd_backend =
1142 34 : GetTempNamespaceBackendId(relation->rd_rel->relnamespace);
1143 : Assert(relation->rd_backend != InvalidBackendId);
1144 34 : relation->rd_islocaltemp = false;
1145 : }
1146 14204 : break;
1147 0 : default:
1148 0 : elog(ERROR, "invalid relpersistence: %c",
1149 : relation->rd_rel->relpersistence);
1150 : break;
1151 : }
1152 :
1153 : /*
1154 : * initialize the tuple descriptor (relation->rd_att).
1155 : */
1156 881526 : RelationBuildTupleDesc(relation);
1157 :
1158 : /*
1159 : * Fetch rules and triggers that affect this relation
1160 : */
1161 881526 : if (relation->rd_rel->relhasrules)
1162 74462 : RelationBuildRuleLock(relation);
1163 : else
1164 : {
1165 807064 : relation->rd_rules = NULL;
1166 807064 : relation->rd_rulescxt = NULL;
1167 : }
1168 :
1169 881526 : if (relation->rd_rel->relhastriggers)
1170 28078 : RelationBuildTriggers(relation);
1171 : else
1172 853448 : relation->trigdesc = NULL;
1173 :
1174 881526 : if (relation->rd_rel->relrowsecurity)
1175 1132 : RelationBuildRowSecurity(relation);
1176 : else
1177 880394 : relation->rd_rsdesc = NULL;
1178 :
1179 : /* foreign key data is not loaded till asked for */
1180 881526 : relation->rd_fkeylist = NIL;
1181 881526 : relation->rd_fkeyvalid = false;
1182 :
1183 : /* partitioning data is not loaded till asked for */
1184 881526 : relation->rd_partkey = NULL;
1185 881526 : relation->rd_partkeycxt = NULL;
1186 881526 : relation->rd_partdesc = NULL;
1187 881526 : relation->rd_pdcxt = NULL;
1188 881526 : relation->rd_partcheck = NIL;
1189 881526 : relation->rd_partcheckvalid = false;
1190 881526 : relation->rd_partcheckcxt = NULL;
1191 :
1192 : /*
1193 : * initialize access method information
1194 : */
1195 881526 : switch (relation->rd_rel->relkind)
1196 : {
1197 288500 : case RELKIND_INDEX:
1198 : case RELKIND_PARTITIONED_INDEX:
1199 : Assert(relation->rd_rel->relam != InvalidOid);
1200 288500 : RelationInitIndexAccessInfo(relation);
1201 288496 : break;
1202 435772 : case RELKIND_RELATION:
1203 : case RELKIND_TOASTVALUE:
1204 : case RELKIND_MATVIEW:
1205 : Assert(relation->rd_rel->relam != InvalidOid);
1206 435772 : RelationInitTableAccessMethod(relation);
1207 435772 : break;
1208 2724 : case RELKIND_SEQUENCE:
1209 : Assert(relation->rd_rel->relam == InvalidOid);
1210 2724 : RelationInitTableAccessMethod(relation);
1211 2724 : break;
1212 154530 : case RELKIND_VIEW:
1213 : case RELKIND_COMPOSITE_TYPE:
1214 : case RELKIND_FOREIGN_TABLE:
1215 : case RELKIND_PARTITIONED_TABLE:
1216 : Assert(relation->rd_rel->relam == InvalidOid);
1217 154530 : break;
1218 : }
1219 :
1220 : /* extract reloptions if any */
1221 881522 : RelationParseRelOptions(relation, pg_class_tuple);
1222 :
1223 : /*
1224 : * initialize the relation lock manager information
1225 : */
1226 881522 : RelationInitLockInfo(relation); /* see lmgr.c */
1227 :
1228 : /*
1229 : * initialize physical addressing information for the relation
1230 : */
1231 881522 : RelationInitPhysicalAddr(relation);
1232 :
1233 : /* make sure relation is marked as having no open file yet */
1234 881522 : relation->rd_smgr = NULL;
1235 :
1236 : /*
1237 : * now we can free the memory allocated for pg_class_tuple
1238 : */
1239 881522 : heap_freetuple(pg_class_tuple);
1240 :
1241 : /*
1242 : * Insert newly created relation into relcache hash table, if requested.
1243 : *
1244 : * There is one scenario in which we might find a hashtable entry already
1245 : * present, even though our caller failed to find it: if the relation is a
1246 : * system catalog or index that's used during relcache load, we might have
1247 : * recursively created the same relcache entry during the preceding steps.
1248 : * So allow RelationCacheInsert to delete any already-present relcache
1249 : * entry for the same OID. The already-present entry should have refcount
1250 : * zero (else somebody forgot to close it); in the event that it doesn't,
1251 : * we'll elog a WARNING and leak the already-present entry.
1252 : */
1253 881522 : if (insertIt)
1254 557182 : RelationCacheInsert(relation, true);
1255 :
1256 : /* It's fully valid */
1257 881522 : relation->rd_isvalid = true;
1258 :
1259 : #ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1260 : if (tmpcxt)
1261 : {
1262 : /* Return to caller's context, and blow away the temporary context */
1263 : MemoryContextSwitchTo(oldcxt);
1264 : MemoryContextDelete(tmpcxt);
1265 : }
1266 : #endif
1267 :
1268 881522 : return relation;
1269 : }
1270 :
1271 : /*
1272 : * Initialize the physical addressing info (RelFileNode) for a relcache entry
1273 : *
1274 : * Note: at the physical level, relations in the pg_global tablespace must
1275 : * be treated as shared, even if relisshared isn't set. Hence we do not
1276 : * look at relisshared here.
1277 : */
1278 : static void
1279 2955134 : RelationInitPhysicalAddr(Relation relation)
1280 : {
1281 2955134 : Oid oldnode = relation->rd_node.relNode;
1282 :
1283 : /* these relations kinds never have storage */
1284 2955134 : if (!RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
1285 217316 : return;
1286 :
1287 2737818 : if (relation->rd_rel->reltablespace)
1288 379108 : relation->rd_node.spcNode = relation->rd_rel->reltablespace;
1289 : else
1290 2358710 : relation->rd_node.spcNode = MyDatabaseTableSpace;
1291 2737818 : if (relation->rd_node.spcNode == GLOBALTABLESPACE_OID)
1292 377520 : relation->rd_node.dbNode = InvalidOid;
1293 : else
1294 2360298 : relation->rd_node.dbNode = MyDatabaseId;
1295 :
1296 2737818 : if (relation->rd_rel->relfilenode)
1297 : {
1298 : /*
1299 : * Even if we are using a decoding snapshot that doesn't represent the
1300 : * current state of the catalog we need to make sure the filenode
1301 : * points to the current file since the older file will be gone (or
1302 : * truncated). The new file will still contain older rows so lookups
1303 : * in them will work correctly. This wouldn't work correctly if
1304 : * rewrites were allowed to change the schema in an incompatible way,
1305 : * but those are prevented both on catalog tables and on user tables
1306 : * declared as additional catalog tables.
1307 : */
1308 1691442 : if (HistoricSnapshotActive()
1309 2488 : && RelationIsAccessibleInLogicalDecoding(relation)
1310 1808 : && IsTransactionState())
1311 : {
1312 : HeapTuple phys_tuple;
1313 : Form_pg_class physrel;
1314 :
1315 1808 : phys_tuple = ScanPgRelation(RelationGetRelid(relation),
1316 1808 : RelationGetRelid(relation) != ClassOidIndexId,
1317 : true);
1318 1808 : if (!HeapTupleIsValid(phys_tuple))
1319 0 : elog(ERROR, "could not find pg_class entry for %u",
1320 : RelationGetRelid(relation));
1321 1808 : physrel = (Form_pg_class) GETSTRUCT(phys_tuple);
1322 :
1323 1808 : relation->rd_rel->reltablespace = physrel->reltablespace;
1324 1808 : relation->rd_rel->relfilenode = physrel->relfilenode;
1325 1808 : heap_freetuple(phys_tuple);
1326 : }
1327 :
1328 1691442 : relation->rd_node.relNode = relation->rd_rel->relfilenode;
1329 : }
1330 : else
1331 : {
1332 : /* Consult the relation mapper */
1333 1046376 : relation->rd_node.relNode =
1334 1046376 : RelationMapOidToFilenode(relation->rd_id,
1335 1046376 : relation->rd_rel->relisshared);
1336 1046376 : if (!OidIsValid(relation->rd_node.relNode))
1337 0 : elog(ERROR, "could not find relation mapping for relation \"%s\", OID %u",
1338 : RelationGetRelationName(relation), relation->rd_id);
1339 : }
1340 :
1341 : /*
1342 : * For RelationNeedsWAL() to answer correctly on parallel workers, restore
1343 : * rd_firstRelfilenodeSubid. No subtransactions start or end while in
1344 : * parallel mode, so the specific SubTransactionId does not matter.
1345 : */
1346 2737818 : if (IsParallelWorker() && oldnode != relation->rd_node.relNode)
1347 : {
1348 22698 : if (RelFileNodeSkippingWAL(relation->rd_node))
1349 2 : relation->rd_firstRelfilenodeSubid = TopSubTransactionId;
1350 : else
1351 22696 : relation->rd_firstRelfilenodeSubid = InvalidSubTransactionId;
1352 : }
1353 : }
1354 :
1355 : /*
1356 : * Fill in the IndexAmRoutine for an index relation.
1357 : *
1358 : * relation's rd_amhandler and rd_indexcxt must be valid already.
1359 : */
1360 : static void
1361 1095696 : InitIndexAmRoutine(Relation relation)
1362 : {
1363 : IndexAmRoutine *cached,
1364 : *tmp;
1365 :
1366 : /*
1367 : * Call the amhandler in current, short-lived memory context, just in case
1368 : * it leaks anything (it probably won't, but let's be paranoid).
1369 : */
1370 1095696 : tmp = GetIndexAmRoutine(relation->rd_amhandler);
1371 :
1372 : /* OK, now transfer the data into relation's rd_indexcxt. */
1373 1095696 : cached = (IndexAmRoutine *) MemoryContextAlloc(relation->rd_indexcxt,
1374 : sizeof(IndexAmRoutine));
1375 1095696 : memcpy(cached, tmp, sizeof(IndexAmRoutine));
1376 1095696 : relation->rd_indam = cached;
1377 :
1378 1095696 : pfree(tmp);
1379 1095696 : }
1380 :
1381 : /*
1382 : * Initialize index-access-method support data for an index relation
1383 : */
1384 : void
1385 349504 : RelationInitIndexAccessInfo(Relation relation)
1386 : {
1387 : HeapTuple tuple;
1388 : Form_pg_am aform;
1389 : Datum indcollDatum;
1390 : Datum indclassDatum;
1391 : Datum indoptionDatum;
1392 : bool isnull;
1393 : oidvector *indcoll;
1394 : oidvector *indclass;
1395 : int2vector *indoption;
1396 : MemoryContext indexcxt;
1397 : MemoryContext oldcontext;
1398 : int indnatts;
1399 : int indnkeyatts;
1400 : uint16 amsupport;
1401 :
1402 : /*
1403 : * Make a copy of the pg_index entry for the index. Since pg_index
1404 : * contains variable-length and possibly-null fields, we have to do this
1405 : * honestly rather than just treating it as a Form_pg_index struct.
1406 : */
1407 349504 : tuple = SearchSysCache1(INDEXRELID,
1408 349504 : ObjectIdGetDatum(RelationGetRelid(relation)));
1409 349504 : if (!HeapTupleIsValid(tuple))
1410 0 : elog(ERROR, "cache lookup failed for index %u",
1411 : RelationGetRelid(relation));
1412 349504 : oldcontext = MemoryContextSwitchTo(CacheMemoryContext);
1413 349504 : relation->rd_indextuple = heap_copytuple(tuple);
1414 349504 : relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1415 349504 : MemoryContextSwitchTo(oldcontext);
1416 349504 : ReleaseSysCache(tuple);
1417 :
1418 : /*
1419 : * Look up the index's access method, save the OID of its handler function
1420 : */
1421 349504 : tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1422 349504 : if (!HeapTupleIsValid(tuple))
1423 0 : elog(ERROR, "cache lookup failed for access method %u",
1424 : relation->rd_rel->relam);
1425 349504 : aform = (Form_pg_am) GETSTRUCT(tuple);
1426 349504 : relation->rd_amhandler = aform->amhandler;
1427 349504 : ReleaseSysCache(tuple);
1428 :
1429 349504 : indnatts = RelationGetNumberOfAttributes(relation);
1430 349504 : if (indnatts != IndexRelationGetNumberOfAttributes(relation))
1431 0 : elog(ERROR, "relnatts disagrees with indnatts for index %u",
1432 : RelationGetRelid(relation));
1433 349504 : indnkeyatts = IndexRelationGetNumberOfKeyAttributes(relation);
1434 :
1435 : /*
1436 : * Make the private context to hold index access info. The reason we need
1437 : * a context, and not just a couple of pallocs, is so that we won't leak
1438 : * any subsidiary info attached to fmgr lookup records.
1439 : */
1440 349504 : indexcxt = AllocSetContextCreate(CacheMemoryContext,
1441 : "index info",
1442 : ALLOCSET_SMALL_SIZES);
1443 349504 : relation->rd_indexcxt = indexcxt;
1444 349504 : MemoryContextCopyAndSetIdentifier(indexcxt,
1445 : RelationGetRelationName(relation));
1446 :
1447 : /*
1448 : * Now we can fetch the index AM's API struct
1449 : */
1450 349504 : InitIndexAmRoutine(relation);
1451 :
1452 : /*
1453 : * Allocate arrays to hold data. Opclasses are not used for included
1454 : * columns, so allocate them for indnkeyatts only.
1455 : */
1456 349504 : relation->rd_opfamily = (Oid *)
1457 349504 : MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1458 349504 : relation->rd_opcintype = (Oid *)
1459 349504 : MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1460 :
1461 349504 : amsupport = relation->rd_indam->amsupport;
1462 349504 : if (amsupport > 0)
1463 : {
1464 349504 : int nsupport = indnatts * amsupport;
1465 :
1466 349504 : relation->rd_support = (RegProcedure *)
1467 349504 : MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1468 349504 : relation->rd_supportinfo = (FmgrInfo *)
1469 349504 : MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1470 : }
1471 : else
1472 : {
1473 0 : relation->rd_support = NULL;
1474 0 : relation->rd_supportinfo = NULL;
1475 : }
1476 :
1477 349504 : relation->rd_indcollation = (Oid *)
1478 349504 : MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1479 :
1480 349504 : relation->rd_indoption = (int16 *)
1481 349504 : MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(int16));
1482 :
1483 : /*
1484 : * indcollation cannot be referenced directly through the C struct,
1485 : * because it comes after the variable-width indkey field. Must extract
1486 : * the datum the hard way...
1487 : */
1488 349504 : indcollDatum = fastgetattr(relation->rd_indextuple,
1489 : Anum_pg_index_indcollation,
1490 : GetPgIndexDescriptor(),
1491 : &isnull);
1492 : Assert(!isnull);
1493 349504 : indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1494 349504 : memcpy(relation->rd_indcollation, indcoll->values, indnkeyatts * sizeof(Oid));
1495 :
1496 : /*
1497 : * indclass cannot be referenced directly through the C struct, because it
1498 : * comes after the variable-width indkey field. Must extract the datum
1499 : * the hard way...
1500 : */
1501 349504 : indclassDatum = fastgetattr(relation->rd_indextuple,
1502 : Anum_pg_index_indclass,
1503 : GetPgIndexDescriptor(),
1504 : &isnull);
1505 : Assert(!isnull);
1506 349504 : indclass = (oidvector *) DatumGetPointer(indclassDatum);
1507 :
1508 : /*
1509 : * Fill the support procedure OID array, as well as the info about
1510 : * opfamilies and opclass input types. (aminfo and supportinfo are left
1511 : * as zeroes, and are filled on-the-fly when used)
1512 : */
1513 349504 : IndexSupportInitialize(indclass, relation->rd_support,
1514 : relation->rd_opfamily, relation->rd_opcintype,
1515 : amsupport, indnkeyatts);
1516 :
1517 : /*
1518 : * Similarly extract indoption and copy it to the cache entry
1519 : */
1520 349504 : indoptionDatum = fastgetattr(relation->rd_indextuple,
1521 : Anum_pg_index_indoption,
1522 : GetPgIndexDescriptor(),
1523 : &isnull);
1524 : Assert(!isnull);
1525 349504 : indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1526 349504 : memcpy(relation->rd_indoption, indoption->values, indnkeyatts * sizeof(int16));
1527 :
1528 349504 : (void) RelationGetIndexAttOptions(relation, false);
1529 :
1530 : /*
1531 : * expressions, predicate, exclusion caches will be filled later
1532 : */
1533 349500 : relation->rd_indexprs = NIL;
1534 349500 : relation->rd_indpred = NIL;
1535 349500 : relation->rd_exclops = NULL;
1536 349500 : relation->rd_exclprocs = NULL;
1537 349500 : relation->rd_exclstrats = NULL;
1538 349500 : relation->rd_amcache = NULL;
1539 349500 : }
1540 :
1541 : /*
1542 : * IndexSupportInitialize
1543 : * Initializes an index's cached opclass information,
1544 : * given the index's pg_index.indclass entry.
1545 : *
1546 : * Data is returned into *indexSupport, *opFamily, and *opcInType,
1547 : * which are arrays allocated by the caller.
1548 : *
1549 : * The caller also passes maxSupportNumber and maxAttributeNumber, since these
1550 : * indicate the size of the arrays it has allocated --- but in practice these
1551 : * numbers must always match those obtainable from the system catalog entries
1552 : * for the index and access method.
1553 : */
1554 : static void
1555 349504 : IndexSupportInitialize(oidvector *indclass,
1556 : RegProcedure *indexSupport,
1557 : Oid *opFamily,
1558 : Oid *opcInType,
1559 : StrategyNumber maxSupportNumber,
1560 : AttrNumber maxAttributeNumber)
1561 : {
1562 : int attIndex;
1563 :
1564 949442 : for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
1565 : {
1566 : OpClassCacheEnt *opcentry;
1567 :
1568 599938 : if (!OidIsValid(indclass->values[attIndex]))
1569 0 : elog(ERROR, "bogus pg_index tuple");
1570 :
1571 : /* look up the info for this opclass, using a cache */
1572 599938 : opcentry = LookupOpclassInfo(indclass->values[attIndex],
1573 : maxSupportNumber);
1574 :
1575 : /* copy cached data into relcache entry */
1576 599938 : opFamily[attIndex] = opcentry->opcfamily;
1577 599938 : opcInType[attIndex] = opcentry->opcintype;
1578 599938 : if (maxSupportNumber > 0)
1579 1199876 : memcpy(&indexSupport[attIndex * maxSupportNumber],
1580 599938 : opcentry->supportProcs,
1581 : maxSupportNumber * sizeof(RegProcedure));
1582 : }
1583 349504 : }
1584 :
1585 : /*
1586 : * LookupOpclassInfo
1587 : *
1588 : * This routine maintains a per-opclass cache of the information needed
1589 : * by IndexSupportInitialize(). This is more efficient than relying on
1590 : * the catalog cache, because we can load all the info about a particular
1591 : * opclass in a single indexscan of pg_amproc.
1592 : *
1593 : * The information from pg_am about expected range of support function
1594 : * numbers is passed in, rather than being looked up, mainly because the
1595 : * caller will have it already.
1596 : *
1597 : * Note there is no provision for flushing the cache. This is OK at the
1598 : * moment because there is no way to ALTER any interesting properties of an
1599 : * existing opclass --- all you can do is drop it, which will result in
1600 : * a useless but harmless dead entry in the cache. To support altering
1601 : * opclass membership (not the same as opfamily membership!), we'd need to
1602 : * be able to flush this cache as well as the contents of relcache entries
1603 : * for indexes.
1604 : */
1605 : static OpClassCacheEnt *
1606 599938 : LookupOpclassInfo(Oid operatorClassOid,
1607 : StrategyNumber numSupport)
1608 : {
1609 : OpClassCacheEnt *opcentry;
1610 : bool found;
1611 : Relation rel;
1612 : SysScanDesc scan;
1613 : ScanKeyData skey[3];
1614 : HeapTuple htup;
1615 : bool indexOK;
1616 :
1617 599938 : if (OpClassCache == NULL)
1618 : {
1619 : /* First time through: initialize the opclass cache */
1620 : HASHCTL ctl;
1621 :
1622 11168 : ctl.keysize = sizeof(Oid);
1623 11168 : ctl.entrysize = sizeof(OpClassCacheEnt);
1624 11168 : OpClassCache = hash_create("Operator class cache", 64,
1625 : &ctl, HASH_ELEM | HASH_BLOBS);
1626 :
1627 : /* Also make sure CacheMemoryContext exists */
1628 11168 : if (!CacheMemoryContext)
1629 0 : CreateCacheMemoryContext();
1630 : }
1631 :
1632 599938 : opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,
1633 : (void *) &operatorClassOid,
1634 : HASH_ENTER, &found);
1635 :
1636 599938 : if (!found)
1637 : {
1638 : /* Need to allocate memory for new entry */
1639 38184 : opcentry->valid = false; /* until known OK */
1640 38184 : opcentry->numSupport = numSupport;
1641 :
1642 38184 : if (numSupport > 0)
1643 38184 : opcentry->supportProcs = (RegProcedure *)
1644 38184 : MemoryContextAllocZero(CacheMemoryContext,
1645 38184 : (numSupport + 1) * sizeof(RegProcedure));
1646 : else
1647 0 : opcentry->supportProcs = NULL;
1648 : }
1649 : else
1650 : {
1651 : Assert(numSupport == opcentry->numSupport);
1652 : }
1653 :
1654 : /*
1655 : * When testing for cache-flush hazards, we intentionally disable the
1656 : * operator class cache and force reloading of the info on each call. This
1657 : * is helpful because we want to test the case where a cache flush occurs
1658 : * while we are loading the info, and it's very hard to provoke that if
1659 : * this happens only once per opclass per backend.
1660 : */
1661 : #ifdef CLOBBER_CACHE_ENABLED
1662 : if (debug_invalidate_system_caches_always > 0)
1663 : opcentry->valid = false;
1664 : #endif
1665 :
1666 599938 : if (opcentry->valid)
1667 561754 : return opcentry;
1668 :
1669 : /*
1670 : * Need to fill in new entry.
1671 : *
1672 : * To avoid infinite recursion during startup, force heap scans if we're
1673 : * looking up info for the opclasses used by the indexes we would like to
1674 : * reference here.
1675 : */
1676 46416 : indexOK = criticalRelcachesBuilt ||
1677 8232 : (operatorClassOid != OID_BTREE_OPS_OID &&
1678 6296 : operatorClassOid != INT2_BTREE_OPS_OID);
1679 :
1680 : /*
1681 : * We have to fetch the pg_opclass row to determine its opfamily and
1682 : * opcintype, which are needed to look up related operators and functions.
1683 : * It'd be convenient to use the syscache here, but that probably doesn't
1684 : * work while bootstrapping.
1685 : */
1686 38184 : ScanKeyInit(&skey[0],
1687 : Anum_pg_opclass_oid,
1688 : BTEqualStrategyNumber, F_OIDEQ,
1689 : ObjectIdGetDatum(operatorClassOid));
1690 38184 : rel = table_open(OperatorClassRelationId, AccessShareLock);
1691 38184 : scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
1692 : NULL, 1, skey);
1693 :
1694 38184 : if (HeapTupleIsValid(htup = systable_getnext(scan)))
1695 : {
1696 38184 : Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
1697 :
1698 38184 : opcentry->opcfamily = opclassform->opcfamily;
1699 38184 : opcentry->opcintype = opclassform->opcintype;
1700 : }
1701 : else
1702 0 : elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
1703 :
1704 38184 : systable_endscan(scan);
1705 38184 : table_close(rel, AccessShareLock);
1706 :
1707 : /*
1708 : * Scan pg_amproc to obtain support procs for the opclass. We only fetch
1709 : * the default ones (those with lefttype = righttype = opcintype).
1710 : */
1711 38184 : if (numSupport > 0)
1712 : {
1713 38184 : ScanKeyInit(&skey[0],
1714 : Anum_pg_amproc_amprocfamily,
1715 : BTEqualStrategyNumber, F_OIDEQ,
1716 38184 : ObjectIdGetDatum(opcentry->opcfamily));
1717 38184 : ScanKeyInit(&skey[1],
1718 : Anum_pg_amproc_amproclefttype,
1719 : BTEqualStrategyNumber, F_OIDEQ,
1720 38184 : ObjectIdGetDatum(opcentry->opcintype));
1721 38184 : ScanKeyInit(&skey[2],
1722 : Anum_pg_amproc_amprocrighttype,
1723 : BTEqualStrategyNumber, F_OIDEQ,
1724 38184 : ObjectIdGetDatum(opcentry->opcintype));
1725 38184 : rel = table_open(AccessMethodProcedureRelationId, AccessShareLock);
1726 38184 : scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
1727 : NULL, 3, skey);
1728 :
1729 156630 : while (HeapTupleIsValid(htup = systable_getnext(scan)))
1730 : {
1731 118446 : Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
1732 :
1733 118446 : if (amprocform->amprocnum <= 0 ||
1734 118446 : (StrategyNumber) amprocform->amprocnum > numSupport)
1735 0 : elog(ERROR, "invalid amproc number %d for opclass %u",
1736 : amprocform->amprocnum, operatorClassOid);
1737 :
1738 236892 : opcentry->supportProcs[amprocform->amprocnum - 1] =
1739 118446 : amprocform->amproc;
1740 : }
1741 :
1742 38184 : systable_endscan(scan);
1743 38184 : table_close(rel, AccessShareLock);
1744 : }
1745 :
1746 38184 : opcentry->valid = true;
1747 38184 : return opcentry;
1748 : }
1749 :
1750 : /*
1751 : * Fill in the TableAmRoutine for a relation
1752 : *
1753 : * relation's rd_amhandler must be valid already.
1754 : */
1755 : static void
1756 955432 : InitTableAmRoutine(Relation relation)
1757 : {
1758 955432 : relation->rd_tableam = GetTableAmRoutine(relation->rd_amhandler);
1759 955432 : }
1760 :
1761 : /*
1762 : * Initialize table access method support for a table like relation
1763 : */
1764 : void
1765 955432 : RelationInitTableAccessMethod(Relation relation)
1766 : {
1767 : HeapTuple tuple;
1768 : Form_pg_am aform;
1769 :
1770 955432 : if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
1771 : {
1772 : /*
1773 : * Sequences are currently accessed like heap tables, but it doesn't
1774 : * seem prudent to show that in the catalog. So just overwrite it
1775 : * here.
1776 : */
1777 3708 : relation->rd_amhandler = F_HEAP_TABLEAM_HANDLER;
1778 : }
1779 951724 : else if (IsCatalogRelation(relation))
1780 : {
1781 : /*
1782 : * Avoid doing a syscache lookup for catalog tables.
1783 : */
1784 : Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID);
1785 730460 : relation->rd_amhandler = F_HEAP_TABLEAM_HANDLER;
1786 : }
1787 : else
1788 : {
1789 : /*
1790 : * Look up the table access method, save the OID of its handler
1791 : * function.
1792 : */
1793 : Assert(relation->rd_rel->relam != InvalidOid);
1794 221264 : tuple = SearchSysCache1(AMOID,
1795 221264 : ObjectIdGetDatum(relation->rd_rel->relam));
1796 221264 : if (!HeapTupleIsValid(tuple))
1797 0 : elog(ERROR, "cache lookup failed for access method %u",
1798 : relation->rd_rel->relam);
1799 221264 : aform = (Form_pg_am) GETSTRUCT(tuple);
1800 221264 : relation->rd_amhandler = aform->amhandler;
1801 221264 : ReleaseSysCache(tuple);
1802 : }
1803 :
1804 : /*
1805 : * Now we can fetch the table AM's API struct
1806 : */
1807 955432 : InitTableAmRoutine(relation);
1808 955432 : }
1809 :
1810 : /*
1811 : * formrdesc
1812 : *
1813 : * This is a special cut-down version of RelationBuildDesc(),
1814 : * used while initializing the relcache.
1815 : * The relation descriptor is built just from the supplied parameters,
1816 : * without actually looking at any system table entries. We cheat
1817 : * quite a lot since we only need to work for a few basic system
1818 : * catalogs.
1819 : *
1820 : * The catalogs this is used for can't have constraints (except attnotnull),
1821 : * default values, rules, or triggers, since we don't cope with any of that.
1822 : * (Well, actually, this only matters for properties that need to be valid
1823 : * during bootstrap or before RelationCacheInitializePhase3 runs, and none of
1824 : * these properties matter then...)
1825 : *
1826 : * NOTE: we assume we are already switched into CacheMemoryContext.
1827 : */
1828 : static void
1829 18794 : formrdesc(const char *relationName, Oid relationReltype,
1830 : bool isshared,
1831 : int natts, const FormData_pg_attribute *attrs)
1832 : {
1833 : Relation relation;
1834 : int i;
1835 : bool has_not_null;
1836 :
1837 : /*
1838 : * allocate new relation desc, clear all fields of reldesc
1839 : */
1840 18794 : relation = (Relation) palloc0(sizeof(RelationData));
1841 :
1842 : /* make sure relation is marked as having no open file yet */
1843 18794 : relation->rd_smgr = NULL;
1844 :
1845 : /*
1846 : * initialize reference count: 1 because it is nailed in cache
1847 : */
1848 18794 : relation->rd_refcnt = 1;
1849 :
1850 : /*
1851 : * all entries built with this routine are nailed-in-cache; none are for
1852 : * new or temp relations.
1853 : */
1854 18794 : relation->rd_isnailed = true;
1855 18794 : relation->rd_createSubid = InvalidSubTransactionId;
1856 18794 : relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
1857 18794 : relation->rd_firstRelfilenodeSubid = InvalidSubTransactionId;
1858 18794 : relation->rd_droppedSubid = InvalidSubTransactionId;
1859 18794 : relation->rd_backend = InvalidBackendId;
1860 18794 : relation->rd_islocaltemp = false;
1861 :
1862 : /*
1863 : * initialize relation tuple form
1864 : *
1865 : * The data we insert here is pretty incomplete/bogus, but it'll serve to
1866 : * get us launched. RelationCacheInitializePhase3() will read the real
1867 : * data from pg_class and replace what we've done here. Note in
1868 : * particular that relowner is left as zero; this cues
1869 : * RelationCacheInitializePhase3 that the real data isn't there yet.
1870 : */
1871 18794 : relation->rd_rel = (Form_pg_class) palloc0(CLASS_TUPLE_SIZE);
1872 :
1873 18794 : namestrcpy(&relation->rd_rel->relname, relationName);
1874 18794 : relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
1875 18794 : relation->rd_rel->reltype = relationReltype;
1876 :
1877 : /*
1878 : * It's important to distinguish between shared and non-shared relations,
1879 : * even at bootstrap time, to make sure we know where they are stored.
1880 : */
1881 18794 : relation->rd_rel->relisshared = isshared;
1882 18794 : if (isshared)
1883 11050 : relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID;
1884 :
1885 : /* formrdesc is used only for permanent relations */
1886 18794 : relation->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
1887 :
1888 : /* ... and they're always populated, too */
1889 18794 : relation->rd_rel->relispopulated = true;
1890 :
1891 18794 : relation->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
1892 18794 : relation->rd_rel->relpages = 0;
1893 18794 : relation->rd_rel->reltuples = -1;
1894 18794 : relation->rd_rel->relallvisible = 0;
1895 18794 : relation->rd_rel->relkind = RELKIND_RELATION;
1896 18794 : relation->rd_rel->relnatts = (int16) natts;
1897 18794 : relation->rd_rel->relam = HEAP_TABLE_AM_OID;
1898 :
1899 : /*
1900 : * initialize attribute tuple form
1901 : *
1902 : * Unlike the case with the relation tuple, this data had better be right
1903 : * because it will never be replaced. The data comes from
1904 : * src/include/catalog/ headers via genbki.pl.
1905 : */
1906 18794 : relation->rd_att = CreateTemplateTupleDesc(natts);
1907 18794 : relation->rd_att->tdrefcount = 1; /* mark as refcounted */
1908 :
1909 18794 : relation->rd_att->tdtypeid = relationReltype;
1910 18794 : relation->rd_att->tdtypmod = -1; /* just to be sure */
1911 :
1912 : /*
1913 : * initialize tuple desc info
1914 : */
1915 18794 : has_not_null = false;
1916 348628 : for (i = 0; i < natts; i++)
1917 : {
1918 329834 : memcpy(TupleDescAttr(relation->rd_att, i),
1919 329834 : &attrs[i],
1920 : ATTRIBUTE_FIXED_PART_SIZE);
1921 329834 : has_not_null |= attrs[i].attnotnull;
1922 : /* make sure attcacheoff is valid */
1923 329834 : TupleDescAttr(relation->rd_att, i)->attcacheoff = -1;
1924 : }
1925 :
1926 : /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
1927 18794 : TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
1928 :
1929 : /* mark not-null status */
1930 18794 : if (has_not_null)
1931 : {
1932 18794 : TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
1933 :
1934 18794 : constr->has_not_null = true;
1935 18794 : relation->rd_att->constr = constr;
1936 : }
1937 :
1938 : /*
1939 : * initialize relation id from info in att array (my, this is ugly)
1940 : */
1941 18794 : RelationGetRelid(relation) = TupleDescAttr(relation->rd_att, 0)->attrelid;
1942 :
1943 : /*
1944 : * All relations made with formrdesc are mapped. This is necessarily so
1945 : * because there is no other way to know what filenode they currently
1946 : * have. In bootstrap mode, add them to the initial relation mapper data,
1947 : * specifying that the initial filenode is the same as the OID.
1948 : */
1949 18794 : relation->rd_rel->relfilenode = InvalidOid;
1950 18794 : if (IsBootstrapProcessingMode())
1951 1616 : RelationMapUpdateMap(RelationGetRelid(relation),
1952 : RelationGetRelid(relation),
1953 : isshared, true);
1954 :
1955 : /*
1956 : * initialize the relation lock manager information
1957 : */
1958 18794 : RelationInitLockInfo(relation); /* see lmgr.c */
1959 :
1960 : /*
1961 : * initialize physical addressing information for the relation
1962 : */
1963 18794 : RelationInitPhysicalAddr(relation);
1964 :
1965 : /*
1966 : * initialize the table am handler
1967 : */
1968 18794 : relation->rd_rel->relam = HEAP_TABLE_AM_OID;
1969 18794 : relation->rd_tableam = GetHeapamTableAmRoutine();
1970 :
1971 : /*
1972 : * initialize the rel-has-index flag, using hardwired knowledge
1973 : */
1974 18794 : if (IsBootstrapProcessingMode())
1975 : {
1976 : /* In bootstrap mode, we have no indexes */
1977 1616 : relation->rd_rel->relhasindex = false;
1978 : }
1979 : else
1980 : {
1981 : /* Otherwise, all the rels formrdesc is used for have indexes */
1982 17178 : relation->rd_rel->relhasindex = true;
1983 : }
1984 :
1985 : /*
1986 : * add new reldesc to relcache
1987 : */
1988 18794 : RelationCacheInsert(relation, false);
1989 :
1990 : /* It's fully valid */
1991 18794 : relation->rd_isvalid = true;
1992 18794 : }
1993 :
1994 :
1995 : /* ----------------------------------------------------------------
1996 : * Relation Descriptor Lookup Interface
1997 : * ----------------------------------------------------------------
1998 : */
1999 :
2000 : /*
2001 : * RelationIdGetRelation
2002 : *
2003 : * Lookup a reldesc by OID; make one if not already in cache.
2004 : *
2005 : * Returns NULL if no pg_class row could be found for the given relid
2006 : * (suggesting we are trying to access a just-deleted relation).
2007 : * Any other error is reported via elog.
2008 : *
2009 : * NB: caller should already have at least AccessShareLock on the
2010 : * relation ID, else there are nasty race conditions.
2011 : *
2012 : * NB: relation ref count is incremented, or set to 1 if new entry.
2013 : * Caller should eventually decrement count. (Usually,
2014 : * that happens by calling RelationClose().)
2015 : */
2016 : Relation
2017 33279866 : RelationIdGetRelation(Oid relationId)
2018 : {
2019 : Relation rd;
2020 :
2021 : /* Make sure we're in an xact, even if this ends up being a cache hit */
2022 : Assert(IsTransactionState());
2023 :
2024 : /*
2025 : * first try to find reldesc in the cache
2026 : */
2027 33279866 : RelationIdCacheLookup(relationId, rd);
2028 :
2029 33279866 : if (RelationIsValid(rd))
2030 : {
2031 : /* return NULL for dropped relations */
2032 32740912 : if (rd->rd_droppedSubid != InvalidSubTransactionId)
2033 : {
2034 : Assert(!rd->rd_isvalid);
2035 4 : return NULL;
2036 : }
2037 :
2038 32740908 : RelationIncrementReferenceCount(rd);
2039 : /* revalidate cache entry if necessary */
2040 32740908 : if (!rd->rd_isvalid)
2041 : {
2042 : /*
2043 : * Indexes only have a limited number of possible schema changes,
2044 : * and we don't want to use the full-blown procedure because it's
2045 : * a headache for indexes that reload itself depends on.
2046 : */
2047 492210 : if (rd->rd_rel->relkind == RELKIND_INDEX ||
2048 476488 : rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
2049 15722 : RelationReloadIndexInfo(rd);
2050 : else
2051 476488 : RelationClearRelation(rd, true);
2052 :
2053 : /*
2054 : * Normally entries need to be valid here, but before the relcache
2055 : * has been initialized, not enough infrastructure exists to
2056 : * perform pg_class lookups. The structure of such entries doesn't
2057 : * change, but we still want to update the rd_rel entry. So
2058 : * rd_isvalid = false is left in place for a later lookup.
2059 : */
2060 : Assert(rd->rd_isvalid ||
2061 : (rd->rd_isnailed && !criticalRelcachesBuilt));
2062 : }
2063 32740896 : return rd;
2064 : }
2065 :
2066 : /*
2067 : * no reldesc in the cache, so have RelationBuildDesc() build one and add
2068 : * it.
2069 : */
2070 538954 : rd = RelationBuildDesc(relationId, true);
2071 538954 : if (RelationIsValid(rd))
2072 538946 : RelationIncrementReferenceCount(rd);
2073 538954 : return rd;
2074 : }
2075 :
2076 : /* ----------------------------------------------------------------
2077 : * cache invalidation support routines
2078 : * ----------------------------------------------------------------
2079 : */
2080 :
2081 : /*
2082 : * RelationIncrementReferenceCount
2083 : * Increments relation reference count.
2084 : *
2085 : * Note: bootstrap mode has its own weird ideas about relation refcount
2086 : * behavior; we ought to fix it someday, but for now, just disable
2087 : * reference count ownership tracking in bootstrap mode.
2088 : */
2089 : void
2090 48797216 : RelationIncrementReferenceCount(Relation rel)
2091 : {
2092 48797216 : ResourceOwnerEnlargeRelationRefs(CurrentResourceOwner);
2093 48797216 : rel->rd_refcnt += 1;
2094 48797216 : if (!IsBootstrapProcessingMode())
2095 46617232 : ResourceOwnerRememberRelationRef(CurrentResourceOwner, rel);
2096 48797216 : }
2097 :
2098 : /*
2099 : * RelationDecrementReferenceCount
2100 : * Decrements relation reference count.
2101 : */
2102 : void
2103 48797216 : RelationDecrementReferenceCount(Relation rel)
2104 : {
2105 : Assert(rel->rd_refcnt > 0);
2106 48797216 : rel->rd_refcnt -= 1;
2107 48797216 : if (!IsBootstrapProcessingMode())
2108 46617232 : ResourceOwnerForgetRelationRef(CurrentResourceOwner, rel);
2109 48797216 : }
2110 :
2111 : /*
2112 : * RelationClose - close an open relation
2113 : *
2114 : * Actually, we just decrement the refcount.
2115 : *
2116 : * NOTE: if compiled with -DRELCACHE_FORCE_RELEASE then relcache entries
2117 : * will be freed as soon as their refcount goes to zero. In combination
2118 : * with aset.c's CLOBBER_FREED_MEMORY option, this provides a good test
2119 : * to catch references to already-released relcache entries. It slows
2120 : * things down quite a bit, however.
2121 : */
2122 : void
2123 33489302 : RelationClose(Relation relation)
2124 : {
2125 : /* Note: no locking manipulations needed */
2126 33489302 : RelationDecrementReferenceCount(relation);
2127 :
2128 : /*
2129 : * If the relation is no longer open in this session, we can clean up any
2130 : * stale partition descriptors it has. This is unlikely, so check to see
2131 : * if there are child contexts before expending a call to mcxt.c.
2132 : */
2133 33489302 : if (RelationHasReferenceCountZero(relation) &&
2134 21780960 : relation->rd_pdcxt != NULL &&
2135 40420 : relation->rd_pdcxt->firstchild != NULL)
2136 1818 : MemoryContextDeleteChildren(relation->rd_pdcxt);
2137 :
2138 : #ifdef RELCACHE_FORCE_RELEASE
2139 : if (RelationHasReferenceCountZero(relation) &&
2140 : relation->rd_createSubid == InvalidSubTransactionId &&
2141 : relation->rd_firstRelfilenodeSubid == InvalidSubTransactionId)
2142 : RelationClearRelation(relation, false);
2143 : #endif
2144 33489302 : }
2145 :
2146 : /*
2147 : * RelationReloadIndexInfo - reload minimal information for an open index
2148 : *
2149 : * This function is used only for indexes. A relcache inval on an index
2150 : * can mean that its pg_class or pg_index row changed. There are only
2151 : * very limited changes that are allowed to an existing index's schema,
2152 : * so we can update the relcache entry without a complete rebuild; which
2153 : * is fortunate because we can't rebuild an index entry that is "nailed"
2154 : * and/or in active use. We support full replacement of the pg_class row,
2155 : * as well as updates of a few simple fields of the pg_index row.
2156 : *
2157 : * We can't necessarily reread the catalog rows right away; we might be
2158 : * in a failed transaction when we receive the SI notification. If so,
2159 : * RelationClearRelation just marks the entry as invalid by setting
2160 : * rd_isvalid to false. This routine is called to fix the entry when it
2161 : * is next needed.
2162 : *
2163 : * We assume that at the time we are called, we have at least AccessShareLock
2164 : * on the target index. (Note: in the calls from RelationClearRelation,
2165 : * this is legitimate because we know the rel has positive refcount.)
2166 : *
2167 : * If the target index is an index on pg_class or pg_index, we'd better have
2168 : * previously gotten at least AccessShareLock on its underlying catalog,
2169 : * else we are at risk of deadlock against someone trying to exclusive-lock
2170 : * the heap and index in that order. This is ensured in current usage by
2171 : * only applying this to indexes being opened or having positive refcount.
2172 : */
2173 : static void
2174 49774 : RelationReloadIndexInfo(Relation relation)
2175 : {
2176 : bool indexOK;
2177 : HeapTuple pg_class_tuple;
2178 : Form_pg_class relp;
2179 :
2180 : /* Should be called only for invalidated, live indexes */
2181 : Assert((relation->rd_rel->relkind == RELKIND_INDEX ||
2182 : relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) &&
2183 : !relation->rd_isvalid &&
2184 : relation->rd_droppedSubid == InvalidSubTransactionId);
2185 :
2186 : /* Ensure it's closed at smgr level */
2187 49774 : RelationCloseSmgr(relation);
2188 :
2189 : /* Must free any AM cached data upon relcache flush */
2190 49774 : if (relation->rd_amcache)
2191 4 : pfree(relation->rd_amcache);
2192 49774 : relation->rd_amcache = NULL;
2193 :
2194 : /*
2195 : * If it's a shared index, we might be called before backend startup has
2196 : * finished selecting a database, in which case we have no way to read
2197 : * pg_class yet. However, a shared index can never have any significant
2198 : * schema updates, so it's okay to ignore the invalidation signal. Just
2199 : * mark it valid and return without doing anything more.
2200 : */
2201 49774 : if (relation->rd_rel->relisshared && !criticalRelcachesBuilt)
2202 : {
2203 0 : relation->rd_isvalid = true;
2204 0 : return;
2205 : }
2206 :
2207 : /*
2208 : * Read the pg_class row
2209 : *
2210 : * Don't try to use an indexscan of pg_class_oid_index to reload the info
2211 : * for pg_class_oid_index ...
2212 : */
2213 49774 : indexOK = (RelationGetRelid(relation) != ClassOidIndexId);
2214 49774 : pg_class_tuple = ScanPgRelation(RelationGetRelid(relation), indexOK, false);
2215 49768 : if (!HeapTupleIsValid(pg_class_tuple))
2216 0 : elog(ERROR, "could not find pg_class tuple for index %u",
2217 : RelationGetRelid(relation));
2218 49768 : relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
2219 49768 : memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE);
2220 : /* Reload reloptions in case they changed */
2221 49768 : if (relation->rd_options)
2222 280 : pfree(relation->rd_options);
2223 49768 : RelationParseRelOptions(relation, pg_class_tuple);
2224 : /* done with pg_class tuple */
2225 49768 : heap_freetuple(pg_class_tuple);
2226 : /* We must recalculate physical address in case it changed */
2227 49768 : RelationInitPhysicalAddr(relation);
2228 :
2229 : /*
2230 : * For a non-system index, there are fields of the pg_index row that are
2231 : * allowed to change, so re-read that row and update the relcache entry.
2232 : * Most of the info derived from pg_index (such as support function lookup
2233 : * info) cannot change, and indeed the whole point of this routine is to
2234 : * update the relcache entry without clobbering that data; so wholesale
2235 : * replacement is not appropriate.
2236 : */
2237 49768 : if (!IsSystemRelation(relation))
2238 : {
2239 : HeapTuple tuple;
2240 : Form_pg_index index;
2241 :
2242 12862 : tuple = SearchSysCache1(INDEXRELID,
2243 12862 : ObjectIdGetDatum(RelationGetRelid(relation)));
2244 12862 : if (!HeapTupleIsValid(tuple))
2245 0 : elog(ERROR, "cache lookup failed for index %u",
2246 : RelationGetRelid(relation));
2247 12862 : index = (Form_pg_index) GETSTRUCT(tuple);
2248 :
2249 : /*
2250 : * Basically, let's just copy all the bool fields. There are one or
2251 : * two of these that can't actually change in the current code, but
2252 : * it's not worth it to track exactly which ones they are. None of
2253 : * the array fields are allowed to change, though.
2254 : */
2255 12862 : relation->rd_index->indisunique = index->indisunique;
2256 12862 : relation->rd_index->indisprimary = index->indisprimary;
2257 12862 : relation->rd_index->indisexclusion = index->indisexclusion;
2258 12862 : relation->rd_index->indimmediate = index->indimmediate;
2259 12862 : relation->rd_index->indisclustered = index->indisclustered;
2260 12862 : relation->rd_index->indisvalid = index->indisvalid;
2261 12862 : relation->rd_index->indcheckxmin = index->indcheckxmin;
2262 12862 : relation->rd_index->indisready = index->indisready;
2263 12862 : relation->rd_index->indislive = index->indislive;
2264 :
2265 : /* Copy xmin too, as that is needed to make sense of indcheckxmin */
2266 12862 : HeapTupleHeaderSetXmin(relation->rd_indextuple->t_data,
2267 : HeapTupleHeaderGetXmin(tuple->t_data));
2268 :
2269 12862 : ReleaseSysCache(tuple);
2270 : }
2271 :
2272 : /* Okay, now it's valid again */
2273 49768 : relation->rd_isvalid = true;
2274 : }
2275 :
2276 : /*
2277 : * RelationReloadNailed - reload minimal information for nailed relations.
2278 : *
2279 : * The structure of a nailed relation can never change (which is good, because
2280 : * we rely on knowing their structure to be able to read catalog content). But
2281 : * some parts, e.g. pg_class.relfrozenxid, are still important to have
2282 : * accurate content for. Therefore those need to be reloaded after the arrival
2283 : * of invalidations.
2284 : */
2285 : static void
2286 561350 : RelationReloadNailed(Relation relation)
2287 : {
2288 : Assert(relation->rd_isnailed);
2289 :
2290 : /*
2291 : * Redo RelationInitPhysicalAddr in case it is a mapped relation whose
2292 : * mapping changed.
2293 : */
2294 561350 : RelationInitPhysicalAddr(relation);
2295 :
2296 : /* flag as needing to be revalidated */
2297 561350 : relation->rd_isvalid = false;
2298 :
2299 : /*
2300 : * Can only reread catalog contents if in a transaction. If the relation
2301 : * is currently open (not counting the nailed refcount), do so
2302 : * immediately. Otherwise we've already marked the entry as possibly
2303 : * invalid, and it'll be fixed when next opened.
2304 : */
2305 561350 : if (!IsTransactionState() || relation->rd_refcnt <= 1)
2306 73928 : return;
2307 :
2308 487422 : if (relation->rd_rel->relkind == RELKIND_INDEX)
2309 : {
2310 : /*
2311 : * If it's a nailed-but-not-mapped index, then we need to re-read the
2312 : * pg_class row to see if its relfilenode changed.
2313 : */
2314 908 : RelationReloadIndexInfo(relation);
2315 : }
2316 : else
2317 : {
2318 : /*
2319 : * Reload a non-index entry. We can't easily do so if relcaches
2320 : * aren't yet built, but that's fine because at that stage the
2321 : * attributes that need to be current (like relfrozenxid) aren't yet
2322 : * accessed. To ensure the entry will later be revalidated, we leave
2323 : * it in invalid state, but allow use (cf. RelationIdGetRelation()).
2324 : */
2325 486514 : if (criticalRelcachesBuilt)
2326 : {
2327 : HeapTuple pg_class_tuple;
2328 : Form_pg_class relp;
2329 :
2330 : /*
2331 : * NB: Mark the entry as valid before starting to scan, to avoid
2332 : * self-recursion when re-building pg_class.
2333 : */
2334 19812 : relation->rd_isvalid = true;
2335 :
2336 19812 : pg_class_tuple = ScanPgRelation(RelationGetRelid(relation),
2337 : true, false);
2338 19806 : relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
2339 19806 : memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE);
2340 19806 : heap_freetuple(pg_class_tuple);
2341 :
2342 : /*
2343 : * Again mark as valid, to protect against concurrently arriving
2344 : * invalidations.
2345 : */
2346 19806 : relation->rd_isvalid = true;
2347 : }
2348 : }
2349 : }
2350 :
2351 : /*
2352 : * RelationDestroyRelation
2353 : *
2354 : * Physically delete a relation cache entry and all subsidiary data.
2355 : * Caller must already have unhooked the entry from the hash table.
2356 : */
2357 : static void
2358 850048 : RelationDestroyRelation(Relation relation, bool remember_tupdesc)
2359 : {
2360 : Assert(RelationHasReferenceCountZero(relation));
2361 :
2362 : /*
2363 : * Make sure smgr and lower levels close the relation's files, if they
2364 : * weren't closed already. (This was probably done by caller, but let's
2365 : * just be real sure.)
2366 : */
2367 850048 : RelationCloseSmgr(relation);
2368 :
2369 : /*
2370 : * Free all the subsidiary data structures of the relcache entry, then the
2371 : * entry itself.
2372 : */
2373 850048 : if (relation->rd_rel)
2374 850048 : pfree(relation->rd_rel);
2375 : /* can't use DecrTupleDescRefCount here */
2376 : Assert(relation->rd_att->tdrefcount > 0);
2377 850048 : if (--relation->rd_att->tdrefcount == 0)
2378 : {
2379 : /*
2380 : * If we Rebuilt a relcache entry during a transaction then its
2381 : * possible we did that because the TupDesc changed as the result of
2382 : * an ALTER TABLE that ran at less than AccessExclusiveLock. It's
2383 : * possible someone copied that TupDesc, in which case the copy would
2384 : * point to free'd memory. So if we rebuild an entry we keep the
2385 : * TupDesc around until end of transaction, to be safe.
2386 : */
2387 848538 : if (remember_tupdesc)
2388 10106 : RememberToFreeTupleDescAtEOX(relation->rd_att);
2389 : else
2390 838432 : FreeTupleDesc(relation->rd_att);
2391 : }
2392 850048 : FreeTriggerDesc(relation->trigdesc);
2393 850048 : list_free_deep(relation->rd_fkeylist);
2394 850048 : list_free(relation->rd_indexlist);
2395 850048 : bms_free(relation->rd_indexattr);
2396 850048 : bms_free(relation->rd_keyattr);
2397 850048 : bms_free(relation->rd_pkattr);
2398 850048 : bms_free(relation->rd_idattr);
2399 850048 : if (relation->rd_pubactions)
2400 2110 : pfree(relation->rd_pubactions);
2401 850048 : if (relation->rd_options)
2402 5260 : pfree(relation->rd_options);
2403 850048 : if (relation->rd_indextuple)
2404 190746 : pfree(relation->rd_indextuple);
2405 850048 : if (relation->rd_amcache)
2406 0 : pfree(relation->rd_amcache);
2407 850048 : if (relation->rd_fdwroutine)
2408 170 : pfree(relation->rd_fdwroutine);
2409 850048 : if (relation->rd_indexcxt)
2410 190746 : MemoryContextDelete(relation->rd_indexcxt);
2411 850048 : if (relation->rd_rulescxt)
2412 61732 : MemoryContextDelete(relation->rd_rulescxt);
2413 850048 : if (relation->rd_rsdesc)
2414 1058 : MemoryContextDelete(relation->rd_rsdesc->rscxt);
2415 850048 : if (relation->rd_partkeycxt)
2416 7794 : MemoryContextDelete(relation->rd_partkeycxt);
2417 850048 : if (relation->rd_pdcxt)
2418 7550 : MemoryContextDelete(relation->rd_pdcxt);
2419 850048 : if (relation->rd_partcheckcxt)
2420 1302 : MemoryContextDelete(relation->rd_partcheckcxt);
2421 850048 : pfree(relation);
2422 850048 : }
2423 :
2424 : /*
2425 : * RelationClearRelation
2426 : *
2427 : * Physically blow away a relation cache entry, or reset it and rebuild
2428 : * it from scratch (that is, from catalog entries). The latter path is
2429 : * used when we are notified of a change to an open relation (one with
2430 : * refcount > 0).
2431 : *
2432 : * NB: when rebuilding, we'd better hold some lock on the relation,
2433 : * else the catalog data we need to read could be changing under us.
2434 : * Also, a rel to be rebuilt had better have refcnt > 0. This is because
2435 : * a sinval reset could happen while we're accessing the catalogs, and
2436 : * the rel would get blown away underneath us by RelationCacheInvalidate
2437 : * if it has zero refcnt.
2438 : *
2439 : * The "rebuild" parameter is redundant in current usage because it has
2440 : * to match the relation's refcnt status, but we keep it as a crosscheck
2441 : * that we're doing what the caller expects.
2442 : */
2443 : static void
2444 1445426 : RelationClearRelation(Relation relation, bool rebuild)
2445 : {
2446 : /*
2447 : * As per notes above, a rel to be rebuilt MUST have refcnt > 0; while of
2448 : * course it would be an equally bad idea to blow away one with nonzero
2449 : * refcnt, since that would leave someone somewhere with a dangling
2450 : * pointer. All callers are expected to have verified that this holds.
2451 : */
2452 : Assert(rebuild ?
2453 : !RelationHasReferenceCountZero(relation) :
2454 : RelationHasReferenceCountZero(relation));
2455 :
2456 : /*
2457 : * Make sure smgr and lower levels close the relation's files, if they
2458 : * weren't closed already. If the relation is not getting deleted, the
2459 : * next smgr access should reopen the files automatically. This ensures
2460 : * that the low-level file access state is updated after, say, a vacuum
2461 : * truncation.
2462 : */
2463 1445426 : RelationCloseSmgr(relation);
2464 :
2465 : /* Free AM cached data, if any */
2466 1445426 : if (relation->rd_amcache)
2467 65440 : pfree(relation->rd_amcache);
2468 1445426 : relation->rd_amcache = NULL;
2469 :
2470 : /*
2471 : * Treat nailed-in system relations separately, they always need to be
2472 : * accessible, so we can't blow them away.
2473 : */
2474 1445426 : if (relation->rd_isnailed)
2475 : {
2476 561350 : RelationReloadNailed(relation);
2477 561344 : return;
2478 : }
2479 :
2480 : /* Mark it invalid until we've finished rebuild */
2481 884076 : relation->rd_isvalid = false;
2482 :
2483 : /* See RelationForgetRelation(). */
2484 884076 : if (relation->rd_droppedSubid != InvalidSubTransactionId)
2485 820 : return;
2486 :
2487 : /*
2488 : * Even non-system indexes should not be blown away if they are open and
2489 : * have valid index support information. This avoids problems with active
2490 : * use of the index support information. As with nailed indexes, we
2491 : * re-read the pg_class row to handle possible physical relocation of the
2492 : * index, and we check for pg_index updates too.
2493 : */
2494 883256 : if ((relation->rd_rel->relkind == RELKIND_INDEX ||
2495 645720 : relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) &&
2496 242232 : relation->rd_refcnt > 0 &&
2497 51482 : relation->rd_indexcxt != NULL)
2498 : {
2499 33148 : if (IsTransactionState())
2500 33144 : RelationReloadIndexInfo(relation);
2501 33148 : return;
2502 : }
2503 :
2504 : /*
2505 : * If we're really done with the relcache entry, blow it away. But if
2506 : * someone is still using it, reconstruct the whole deal without moving
2507 : * the physical RelationData record (so that the someone's pointer is
2508 : * still valid).
2509 : */
2510 850108 : if (!rebuild)
2511 : {
2512 : /* Remove it from the hash table */
2513 525708 : RelationCacheDelete(relation);
2514 :
2515 : /* And release storage */
2516 525708 : RelationDestroyRelation(relation, false);
2517 : }
2518 324400 : else if (!IsTransactionState())
2519 : {
2520 : /*
2521 : * If we're not inside a valid transaction, we can't do any catalog
2522 : * access so it's not possible to rebuild yet. Just exit, leaving
2523 : * rd_isvalid = false so that the rebuild will occur when the entry is
2524 : * next opened.
2525 : *
2526 : * Note: it's possible that we come here during subtransaction abort,
2527 : * and the reason for wanting to rebuild is that the rel is open in
2528 : * the outer transaction. In that case it might seem unsafe to not
2529 : * rebuild immediately, since whatever code has the rel already open
2530 : * will keep on using the relcache entry as-is. However, in such a
2531 : * case the outer transaction should be holding a lock that's
2532 : * sufficient to prevent any significant change in the rel's schema,
2533 : * so the existing entry contents should be good enough for its
2534 : * purposes; at worst we might be behind on statistics updates or the
2535 : * like. (See also CheckTableNotInUse() and its callers.) These same
2536 : * remarks also apply to the cases above where we exit without having
2537 : * done RelationReloadIndexInfo() yet.
2538 : */
2539 56 : return;
2540 : }
2541 : else
2542 : {
2543 : /*
2544 : * Our strategy for rebuilding an open relcache entry is to build a
2545 : * new entry from scratch, swap its contents with the old entry, and
2546 : * finally delete the new entry (along with any infrastructure swapped
2547 : * over from the old entry). This is to avoid trouble in case an
2548 : * error causes us to lose control partway through. The old entry
2549 : * will still be marked !rd_isvalid, so we'll try to rebuild it again
2550 : * on next access. Meanwhile it's not any less valid than it was
2551 : * before, so any code that might expect to continue accessing it
2552 : * isn't hurt by the rebuild failure. (Consider for example a
2553 : * subtransaction that ALTERs a table and then gets canceled partway
2554 : * through the cache entry rebuild. The outer transaction should
2555 : * still see the not-modified cache entry as valid.) The worst
2556 : * consequence of an error is leaking the necessarily-unreferenced new
2557 : * entry, and this shouldn't happen often enough for that to be a big
2558 : * problem.
2559 : *
2560 : * When rebuilding an open relcache entry, we must preserve ref count,
2561 : * rd_*Subid, and rd_toastoid state. Also attempt to preserve the
2562 : * pg_class entry (rd_rel), tupledesc, rewrite-rule, partition key,
2563 : * and partition descriptor substructures in place, because various
2564 : * places assume that these structures won't move while they are
2565 : * working with an open relcache entry. (Note: the refcount
2566 : * mechanism for tupledescs might someday allow us to remove this hack
2567 : * for the tupledesc.)
2568 : *
2569 : * Note that this process does not touch CurrentResourceOwner; which
2570 : * is good because whatever ref counts the entry may have do not
2571 : * necessarily belong to that resource owner.
2572 : */
2573 : Relation newrel;
2574 324344 : Oid save_relid = RelationGetRelid(relation);
2575 : bool keep_tupdesc;
2576 : bool keep_rules;
2577 : bool keep_policies;
2578 : bool keep_partkey;
2579 :
2580 : /* Build temporary entry, but don't link it into hashtable */
2581 324344 : newrel = RelationBuildDesc(save_relid, false);
2582 324340 : if (newrel == NULL)
2583 : {
2584 : /*
2585 : * We can validly get here, if we're using a historic snapshot in
2586 : * which a relation, accessed from outside logical decoding, is
2587 : * still invisible. In that case it's fine to just mark the
2588 : * relation as invalid and return - it'll fully get reloaded by
2589 : * the cache reset at the end of logical decoding (or at the next
2590 : * access). During normal processing we don't want to ignore this
2591 : * case as it shouldn't happen there, as explained below.
2592 : */
2593 0 : if (HistoricSnapshotActive())
2594 0 : return;
2595 :
2596 : /*
2597 : * This shouldn't happen as dropping a relation is intended to be
2598 : * impossible if still referenced (cf. CheckTableNotInUse()). But
2599 : * if we get here anyway, we can't just delete the relcache entry,
2600 : * as it possibly could get accessed later (as e.g. the error
2601 : * might get trapped and handled via a subtransaction rollback).
2602 : */
2603 0 : elog(ERROR, "relation %u deleted while still in use", save_relid);
2604 : }
2605 :
2606 324340 : keep_tupdesc = equalTupleDescs(relation->rd_att, newrel->rd_att);
2607 324340 : keep_rules = equalRuleLocks(relation->rd_rules, newrel->rd_rules);
2608 324340 : keep_policies = equalRSDesc(relation->rd_rsdesc, newrel->rd_rsdesc);
2609 : /* partkey is immutable once set up, so we can always keep it */
2610 324340 : keep_partkey = (relation->rd_partkey != NULL);
2611 :
2612 : /*
2613 : * Perform swapping of the relcache entry contents. Within this
2614 : * process the old entry is momentarily invalid, so there *must* be no
2615 : * possibility of CHECK_FOR_INTERRUPTS within this sequence. Do it in
2616 : * all-in-line code for safety.
2617 : *
2618 : * Since the vast majority of fields should be swapped, our method is
2619 : * to swap the whole structures and then re-swap those few fields we
2620 : * didn't want swapped.
2621 : */
2622 : #define SWAPFIELD(fldtype, fldname) \
2623 : do { \
2624 : fldtype _tmp = newrel->fldname; \
2625 : newrel->fldname = relation->fldname; \
2626 : relation->fldname = _tmp; \
2627 : } while (0)
2628 :
2629 : /* swap all Relation struct fields */
2630 : {
2631 : RelationData tmpstruct;
2632 :
2633 324340 : memcpy(&tmpstruct, newrel, sizeof(RelationData));
2634 324340 : memcpy(newrel, relation, sizeof(RelationData));
2635 324340 : memcpy(relation, &tmpstruct, sizeof(RelationData));
2636 : }
2637 :
2638 : /* rd_smgr must not be swapped, due to back-links from smgr level */
2639 324340 : SWAPFIELD(SMgrRelation, rd_smgr);
2640 : /* rd_refcnt must be preserved */
2641 324340 : SWAPFIELD(int, rd_refcnt);
2642 : /* isnailed shouldn't change */
2643 : Assert(newrel->rd_isnailed == relation->rd_isnailed);
2644 : /* creation sub-XIDs must be preserved */
2645 324340 : SWAPFIELD(SubTransactionId, rd_createSubid);
2646 324340 : SWAPFIELD(SubTransactionId, rd_newRelfilenodeSubid);
2647 324340 : SWAPFIELD(SubTransactionId, rd_firstRelfilenodeSubid);
2648 324340 : SWAPFIELD(SubTransactionId, rd_droppedSubid);
2649 : /* un-swap rd_rel pointers, swap contents instead */
2650 324340 : SWAPFIELD(Form_pg_class, rd_rel);
2651 : /* ... but actually, we don't have to update newrel->rd_rel */
2652 324340 : memcpy(relation->rd_rel, newrel->rd_rel, CLASS_TUPLE_SIZE);
2653 : /* preserve old tupledesc, rules, policies if no logical change */
2654 324340 : if (keep_tupdesc)
2655 314104 : SWAPFIELD(TupleDesc, rd_att);
2656 324340 : if (keep_rules)
2657 : {
2658 269222 : SWAPFIELD(RuleLock *, rd_rules);
2659 269222 : SWAPFIELD(MemoryContext, rd_rulescxt);
2660 : }
2661 324340 : if (keep_policies)
2662 324150 : SWAPFIELD(RowSecurityDesc *, rd_rsdesc);
2663 : /* toast OID override must be preserved */
2664 324340 : SWAPFIELD(Oid, rd_toastoid);
2665 : /* pgstat_info must be preserved */
2666 324340 : SWAPFIELD(struct PgStat_TableStatus *, pgstat_info);
2667 : /* preserve old partition key if we have one */
2668 324340 : if (keep_partkey)
2669 : {
2670 5392 : SWAPFIELD(PartitionKey, rd_partkey);
2671 5392 : SWAPFIELD(MemoryContext, rd_partkeycxt);
2672 : }
2673 324340 : if (newrel->rd_pdcxt != NULL)
2674 : {
2675 : /*
2676 : * We are rebuilding a partitioned relation with a non-zero
2677 : * reference count, so we must keep the old partition descriptor
2678 : * around, in case there's a PartitionDirectory with a pointer to
2679 : * it. This means we can't free the old rd_pdcxt yet. (This is
2680 : * necessary because RelationGetPartitionDesc hands out direct
2681 : * pointers to the relcache's data structure, unlike our usual
2682 : * practice which is to hand out copies. We'd have the same
2683 : * problem with rd_partkey, except that we always preserve that
2684 : * once created.)
2685 : *
2686 : * To ensure that it's not leaked completely, re-attach it to the
2687 : * new reldesc, or make it a child of the new reldesc's rd_pdcxt
2688 : * in the unlikely event that there is one already. (Compare hack
2689 : * in RelationBuildPartitionDesc.) RelationClose will clean up
2690 : * any such contexts once the reference count reaches zero.
2691 : *
2692 : * In the case where the reference count is zero, this code is not
2693 : * reached, which should be OK because in that case there should
2694 : * be no PartitionDirectory with a pointer to the old entry.
2695 : *
2696 : * Note that newrel and relation have already been swapped, so the
2697 : * "old" partition descriptor is actually the one hanging off of
2698 : * newrel.
2699 : */
2700 4372 : relation->rd_partdesc = NULL; /* ensure rd_partdesc is invalid */
2701 4372 : if (relation->rd_pdcxt != NULL) /* probably never happens */
2702 0 : MemoryContextSetParent(newrel->rd_pdcxt, relation->rd_pdcxt);
2703 : else
2704 4372 : relation->rd_pdcxt = newrel->rd_pdcxt;
2705 : /* drop newrel's pointers so we don't destroy it below */
2706 4372 : newrel->rd_partdesc = NULL;
2707 4372 : newrel->rd_pdcxt = NULL;
2708 : }
2709 :
2710 : #undef SWAPFIELD
2711 :
2712 : /* And now we can throw away the temporary entry */
2713 324340 : RelationDestroyRelation(newrel, !keep_tupdesc);
2714 : }
2715 : }
2716 :
2717 : /*
2718 : * RelationFlushRelation
2719 : *
2720 : * Rebuild the relation if it is open (refcount > 0), else blow it away.
2721 : * This is used when we receive a cache invalidation event for the rel.
2722 : */
2723 : static void
2724 668126 : RelationFlushRelation(Relation relation)
2725 : {
2726 668126 : if (relation->rd_createSubid != InvalidSubTransactionId ||
2727 351660 : relation->rd_firstRelfilenodeSubid != InvalidSubTransactionId)
2728 : {
2729 : /*
2730 : * New relcache entries are always rebuilt, not flushed; else we'd
2731 : * forget the "new" status of the relation. Ditto for the
2732 : * new-relfilenode status.
2733 : *
2734 : * The rel could have zero refcnt here, so temporarily increment the
2735 : * refcnt to ensure it's safe to rebuild it. We can assume that the
2736 : * current transaction has some lock on the rel already.
2737 : */
2738 326858 : RelationIncrementReferenceCount(relation);
2739 326858 : RelationClearRelation(relation, true);
2740 326854 : RelationDecrementReferenceCount(relation);
2741 : }
2742 : else
2743 : {
2744 : /*
2745 : * Pre-existing rels can be dropped from the relcache if not open.
2746 : */
2747 341268 : bool rebuild = !RelationHasReferenceCountZero(relation);
2748 :
2749 341268 : RelationClearRelation(relation, rebuild);
2750 : }
2751 668122 : }
2752 :
2753 : /*
2754 : * RelationForgetRelation - caller reports that it dropped the relation
2755 : */
2756 : void
2757 36428 : RelationForgetRelation(Oid rid)
2758 : {
2759 : Relation relation;
2760 :
2761 36428 : RelationIdCacheLookup(rid, relation);
2762 :
2763 36428 : if (!PointerIsValid(relation))
2764 0 : return; /* not in cache, nothing to do */
2765 :
2766 36428 : if (!RelationHasReferenceCountZero(relation))
2767 0 : elog(ERROR, "relation %u is still open", rid);
2768 :
2769 : Assert(relation->rd_droppedSubid == InvalidSubTransactionId);
2770 36428 : if (relation->rd_createSubid != InvalidSubTransactionId ||
2771 36036 : relation->rd_firstRelfilenodeSubid != InvalidSubTransactionId)
2772 : {
2773 : /*
2774 : * In the event of subtransaction rollback, we must not forget
2775 : * rd_*Subid. Mark the entry "dropped" so RelationClearRelation()
2776 : * invalidates it in lieu of destroying it. (If we're in a top
2777 : * transaction, we could opt to destroy the entry.)
2778 : */
2779 410 : relation->rd_droppedSubid = GetCurrentSubTransactionId();
2780 : }
2781 :
2782 36428 : RelationClearRelation(relation, false);
2783 : }
2784 :
2785 : /*
2786 : * RelationCacheInvalidateEntry
2787 : *
2788 : * This routine is invoked for SI cache flush messages.
2789 : *
2790 : * Any relcache entry matching the relid must be flushed. (Note: caller has
2791 : * already determined that the relid belongs to our database or is a shared
2792 : * relation.)
2793 : *
2794 : * We used to skip local relations, on the grounds that they could
2795 : * not be targets of cross-backend SI update messages; but it seems
2796 : * safer to process them, so that our *own* SI update messages will
2797 : * have the same effects during CommandCounterIncrement for both
2798 : * local and nonlocal relations.
2799 : */
2800 : void
2801 1489568 : RelationCacheInvalidateEntry(Oid relationId)
2802 : {
2803 : Relation relation;
2804 :
2805 1489568 : RelationIdCacheLookup(relationId, relation);
2806 :
2807 1489568 : if (PointerIsValid(relation))
2808 : {
2809 668126 : relcacheInvalsReceived++;
2810 668126 : RelationFlushRelation(relation);
2811 : }
2812 1489564 : }
2813 :
2814 : /*
2815 : * RelationCacheInvalidate
2816 : * Blow away cached relation descriptors that have zero reference counts,
2817 : * and rebuild those with positive reference counts. Also reset the smgr
2818 : * relation cache and re-read relation mapping data.
2819 : *
2820 : * This is currently used only to recover from SI message buffer overflow,
2821 : * so we do not touch relations having new-in-transaction relfilenodes; they
2822 : * cannot be targets of cross-backend SI updates (and our own updates now go
2823 : * through a separate linked list that isn't limited by the SI message
2824 : * buffer size).
2825 : *
2826 : * We do this in two phases: the first pass deletes deletable items, and
2827 : * the second one rebuilds the rebuildable items. This is essential for
2828 : * safety, because hash_seq_search only copes with concurrent deletion of
2829 : * the element it is currently visiting. If a second SI overflow were to
2830 : * occur while we are walking the table, resulting in recursive entry to
2831 : * this routine, we could crash because the inner invocation blows away
2832 : * the entry next to be visited by the outer scan. But this way is OK,
2833 : * because (a) during the first pass we won't process any more SI messages,
2834 : * so hash_seq_search will complete safely; (b) during the second pass we
2835 : * only hold onto pointers to nondeletable entries.
2836 : *
2837 : * The two-phase approach also makes it easy to update relfilenodes for
2838 : * mapped relations before we do anything else, and to ensure that the
2839 : * second pass processes nailed-in-cache items before other nondeletable
2840 : * items. This should ensure that system catalogs are up to date before
2841 : * we attempt to use them to reload information about other open relations.
2842 : */
2843 : void
2844 2554 : RelationCacheInvalidate(void)
2845 : {
2846 : HASH_SEQ_STATUS status;
2847 : RelIdCacheEnt *idhentry;
2848 : Relation relation;
2849 2554 : List *rebuildFirstList = NIL;
2850 2554 : List *rebuildList = NIL;
2851 : ListCell *l;
2852 :
2853 : /*
2854 : * Reload relation mapping data before starting to reconstruct cache.
2855 : */
2856 2554 : RelationMapInvalidateAll();
2857 :
2858 : /* Phase 1 */
2859 2554 : hash_seq_init(&status, RelationIdCache);
2860 :
2861 264736 : while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2862 : {
2863 262182 : relation = idhentry->reldesc;
2864 :
2865 : /* Must close all smgr references to avoid leaving dangling ptrs */
2866 262182 : RelationCloseSmgr(relation);
2867 :
2868 : /*
2869 : * Ignore new relations; no other backend will manipulate them before
2870 : * we commit. Likewise, before replacing a relation's relfilenode, we
2871 : * shall have acquired AccessExclusiveLock and drained any applicable
2872 : * pending invalidations.
2873 : */
2874 262182 : if (relation->rd_createSubid != InvalidSubTransactionId ||
2875 262166 : relation->rd_firstRelfilenodeSubid != InvalidSubTransactionId)
2876 18 : continue;
2877 :
2878 262164 : relcacheInvalsReceived++;
2879 :
2880 262164 : if (RelationHasReferenceCountZero(relation))
2881 : {
2882 : /* Delete this entry immediately */
2883 : Assert(!relation->rd_isnailed);
2884 206032 : RelationClearRelation(relation, false);
2885 : }
2886 : else
2887 : {
2888 : /*
2889 : * If it's a mapped relation, immediately update its rd_node in
2890 : * case its relfilenode changed. We must do this during phase 1
2891 : * in case the relation is consulted during rebuild of other
2892 : * relcache entries in phase 2. It's safe since consulting the
2893 : * map doesn't involve any access to relcache entries.
2894 : */
2895 56132 : if (RelationIsMapped(relation))
2896 43250 : RelationInitPhysicalAddr(relation);
2897 :
2898 : /*
2899 : * Add this entry to list of stuff to rebuild in second pass.
2900 : * pg_class goes to the front of rebuildFirstList while
2901 : * pg_class_oid_index goes to the back of rebuildFirstList, so
2902 : * they are done first and second respectively. Other nailed
2903 : * relations go to the front of rebuildList, so they'll be done
2904 : * next in no particular order; and everything else goes to the
2905 : * back of rebuildList.
2906 : */
2907 56132 : if (RelationGetRelid(relation) == RelationRelationId)
2908 2540 : rebuildFirstList = lcons(relation, rebuildFirstList);
2909 53592 : else if (RelationGetRelid(relation) == ClassOidIndexId)
2910 2540 : rebuildFirstList = lappend(rebuildFirstList, relation);
2911 51052 : else if (relation->rd_isnailed)
2912 50870 : rebuildList = lcons(relation, rebuildList);
2913 : else
2914 182 : rebuildList = lappend(rebuildList, relation);
2915 : }
2916 : }
2917 :
2918 : /*
2919 : * Now zap any remaining smgr cache entries. This must happen before we
2920 : * start to rebuild entries, since that may involve catalog fetches which
2921 : * will re-open catalog files.
2922 : */
2923 2554 : smgrcloseall();
2924 :
2925 : /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2926 7634 : foreach(l, rebuildFirstList)
2927 : {
2928 5080 : relation = (Relation) lfirst(l);
2929 5080 : RelationClearRelation(relation, true);
2930 : }
2931 2554 : list_free(rebuildFirstList);
2932 53606 : foreach(l, rebuildList)
2933 : {
2934 51052 : relation = (Relation) lfirst(l);
2935 51052 : RelationClearRelation(relation, true);
2936 : }
2937 2554 : list_free(rebuildList);
2938 2554 : }
2939 :
2940 : /*
2941 : * RelationCloseSmgrByOid - close a relcache entry's smgr link
2942 : *
2943 : * Needed in some cases where we are changing a relation's physical mapping.
2944 : * The link will be automatically reopened on next use.
2945 : */
2946 : void
2947 2224 : RelationCloseSmgrByOid(Oid relationId)
2948 : {
2949 : Relation relation;
2950 :
2951 2224 : RelationIdCacheLookup(relationId, relation);
2952 :
2953 2224 : if (!PointerIsValid(relation))
2954 0 : return; /* not in cache, nothing to do */
2955 :
2956 2224 : RelationCloseSmgr(relation);
2957 : }
2958 :
2959 : static void
2960 10106 : RememberToFreeTupleDescAtEOX(TupleDesc td)
2961 : {
2962 10106 : if (EOXactTupleDescArray == NULL)
2963 : {
2964 : MemoryContext oldcxt;
2965 :
2966 6396 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
2967 :
2968 6396 : EOXactTupleDescArray = (TupleDesc *) palloc(16 * sizeof(TupleDesc));
2969 6396 : EOXactTupleDescArrayLen = 16;
2970 6396 : NextEOXactTupleDescNum = 0;
2971 6396 : MemoryContextSwitchTo(oldcxt);
2972 : }
2973 3710 : else if (NextEOXactTupleDescNum >= EOXactTupleDescArrayLen)
2974 : {
2975 8 : int32 newlen = EOXactTupleDescArrayLen * 2;
2976 :
2977 : Assert(EOXactTupleDescArrayLen > 0);
2978 :
2979 8 : EOXactTupleDescArray = (TupleDesc *) repalloc(EOXactTupleDescArray,
2980 : newlen * sizeof(TupleDesc));
2981 8 : EOXactTupleDescArrayLen = newlen;
2982 : }
2983 :
2984 10106 : EOXactTupleDescArray[NextEOXactTupleDescNum++] = td;
2985 10106 : }
2986 :
2987 : #ifdef USE_ASSERT_CHECKING
2988 : static void
2989 : AssertPendingSyncConsistency(Relation relation)
2990 : {
2991 : bool relcache_verdict =
2992 : relation->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT &&
2993 : ((relation->rd_createSubid != InvalidSubTransactionId &&
2994 : RELKIND_HAS_STORAGE(relation->rd_rel->relkind)) ||
2995 : relation->rd_firstRelfilenodeSubid != InvalidSubTransactionId);
2996 :
2997 : Assert(relcache_verdict == RelFileNodeSkippingWAL(relation->rd_node));
2998 :
2999 : if (relation->rd_droppedSubid != InvalidSubTransactionId)
3000 : Assert(!relation->rd_isvalid &&
3001 : (relation->rd_createSubid != InvalidSubTransactionId ||
3002 : relation->rd_firstRelfilenodeSubid != InvalidSubTransactionId));
3003 : }
3004 :
3005 : /*
3006 : * AssertPendingSyncs_RelationCache
3007 : *
3008 : * Assert that relcache.c and storage.c agree on whether to skip WAL.
3009 : */
3010 : void
3011 : AssertPendingSyncs_RelationCache(void)
3012 : {
3013 : HASH_SEQ_STATUS status;
3014 : LOCALLOCK *locallock;
3015 : Relation *rels;
3016 : int maxrels;
3017 : int nrels;
3018 : RelIdCacheEnt *idhentry;
3019 : int i;
3020 :
3021 : /*
3022 : * Open every relation that this transaction has locked. If, for some
3023 : * relation, storage.c is skipping WAL and relcache.c is not skipping WAL,
3024 : * a CommandCounterIncrement() typically yields a local invalidation
3025 : * message that destroys the relcache entry. By recreating such entries
3026 : * here, we detect the problem.
3027 : */
3028 : PushActiveSnapshot(GetTransactionSnapshot());
3029 : maxrels = 1;
3030 : rels = palloc(maxrels * sizeof(*rels));
3031 : nrels = 0;
3032 : hash_seq_init(&status, GetLockMethodLocalHash());
3033 : while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3034 : {
3035 : Oid relid;
3036 : Relation r;
3037 :
3038 : if (locallock->nLocks <= 0)
3039 : continue;
3040 : if ((LockTagType) locallock->tag.lock.locktag_type !=
3041 : LOCKTAG_RELATION)
3042 : continue;
3043 : relid = ObjectIdGetDatum(locallock->tag.lock.locktag_field2);
3044 : r = RelationIdGetRelation(relid);
3045 : if (!RelationIsValid(r))
3046 : continue;
3047 : if (nrels >= maxrels)
3048 : {
3049 : maxrels *= 2;
3050 : rels = repalloc(rels, maxrels * sizeof(*rels));
3051 : }
3052 : rels[nrels++] = r;
3053 : }
3054 :
3055 : hash_seq_init(&status, RelationIdCache);
3056 : while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3057 : AssertPendingSyncConsistency(idhentry->reldesc);
3058 :
3059 : for (i = 0; i < nrels; i++)
3060 : RelationClose(rels[i]);
3061 : PopActiveSnapshot();
3062 : }
3063 : #endif
3064 :
3065 : /*
3066 : * AtEOXact_RelationCache
3067 : *
3068 : * Clean up the relcache at main-transaction commit or abort.
3069 : *
3070 : * Note: this must be called *before* processing invalidation messages.
3071 : * In the case of abort, we don't want to try to rebuild any invalidated
3072 : * cache entries (since we can't safely do database accesses). Therefore
3073 : * we must reset refcnts before handling pending invalidations.
3074 : *
3075 : * As of PostgreSQL 8.1, relcache refcnts should get released by the
3076 : * ResourceOwner mechanism. This routine just does a debugging
3077 : * cross-check that no pins remain. However, we also need to do special
3078 : * cleanup when the current transaction created any relations or made use
3079 : * of forced index lists.
3080 : */
3081 : void
3082 544756 : AtEOXact_RelationCache(bool isCommit)
3083 : {
3084 : HASH_SEQ_STATUS status;
3085 : RelIdCacheEnt *idhentry;
3086 : int i;
3087 :
3088 : /*
3089 : * Unless the eoxact_list[] overflowed, we only need to examine the rels
3090 : * listed in it. Otherwise fall back on a hash_seq_search scan.
3091 : *
3092 : * For simplicity, eoxact_list[] entries are not deleted till end of
3093 : * top-level transaction, even though we could remove them at
3094 : * subtransaction end in some cases, or remove relations from the list if
3095 : * they are cleared for other reasons. Therefore we should expect the
3096 : * case that list entries are not found in the hashtable; if not, there's
3097 : * nothing to do for them.
3098 : */
3099 544756 : if (eoxact_list_overflowed)
3100 : {
3101 408 : hash_seq_init(&status, RelationIdCache);
3102 101068 : while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3103 : {
3104 100660 : AtEOXact_cleanup(idhentry->reldesc, isCommit);
3105 : }
3106 : }
3107 : else
3108 : {
3109 661784 : for (i = 0; i < eoxact_list_len; i++)
3110 : {
3111 117436 : idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3112 117436 : (void *) &eoxact_list[i],
3113 : HASH_FIND,
3114 : NULL);
3115 117436 : if (idhentry != NULL)
3116 116216 : AtEOXact_cleanup(idhentry->reldesc, isCommit);
3117 : }
3118 : }
3119 :
3120 544756 : if (EOXactTupleDescArrayLen > 0)
3121 : {
3122 : Assert(EOXactTupleDescArray != NULL);
3123 16502 : for (i = 0; i < NextEOXactTupleDescNum; i++)
3124 10106 : FreeTupleDesc(EOXactTupleDescArray[i]);
3125 6396 : pfree(EOXactTupleDescArray);
3126 6396 : EOXactTupleDescArray = NULL;
3127 : }
3128 :
3129 : /* Now we're out of the transaction and can clear the lists */
3130 544756 : eoxact_list_len = 0;
3131 544756 : eoxact_list_overflowed = false;
3132 544756 : NextEOXactTupleDescNum = 0;
3133 544756 : EOXactTupleDescArrayLen = 0;
3134 544756 : }
3135 :
3136 : /*
3137 : * AtEOXact_cleanup
3138 : *
3139 : * Clean up a single rel at main-transaction commit or abort
3140 : *
3141 : * NB: this processing must be idempotent, because EOXactListAdd() doesn't
3142 : * bother to prevent duplicate entries in eoxact_list[].
3143 : */
3144 : static void
3145 216876 : AtEOXact_cleanup(Relation relation, bool isCommit)
3146 : {
3147 216876 : bool clear_relcache = false;
3148 :
3149 : /*
3150 : * The relcache entry's ref count should be back to its normal
3151 : * not-in-a-transaction state: 0 unless it's nailed in cache.
3152 : *
3153 : * In bootstrap mode, this is NOT true, so don't check it --- the
3154 : * bootstrap code expects relations to stay open across start/commit
3155 : * transaction calls. (That seems bogus, but it's not worth fixing.)
3156 : *
3157 : * Note: ideally this check would be applied to every relcache entry, not
3158 : * just those that have eoxact work to do. But it's not worth forcing a
3159 : * scan of the whole relcache just for this. (Moreover, doing so would
3160 : * mean that assert-enabled testing never tests the hash_search code path
3161 : * above, which seems a bad idea.)
3162 : */
3163 : #ifdef USE_ASSERT_CHECKING
3164 : if (!IsBootstrapProcessingMode())
3165 : {
3166 : int expected_refcnt;
3167 :
3168 : expected_refcnt = relation->rd_isnailed ? 1 : 0;
3169 : Assert(relation->rd_refcnt == expected_refcnt);
3170 : }
3171 : #endif
3172 :
3173 : /*
3174 : * Is the relation live after this transaction ends?
3175 : *
3176 : * During commit, clear the relcache entry if it is preserved after
3177 : * relation drop, in order not to orphan the entry. During rollback,
3178 : * clear the relcache entry if the relation is created in the current
3179 : * transaction since it isn't interesting any longer once we are out of
3180 : * the transaction.
3181 : */
3182 216876 : clear_relcache =
3183 : (isCommit ?
3184 216876 : relation->rd_droppedSubid != InvalidSubTransactionId :
3185 2146 : relation->rd_createSubid != InvalidSubTransactionId);
3186 :
3187 : /*
3188 : * Since we are now out of the transaction, reset the subids to zero. That
3189 : * also lets RelationClearRelation() drop the relcache entry.
3190 : */
3191 216876 : relation->rd_createSubid = InvalidSubTransactionId;
3192 216876 : relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
3193 216876 : relation->rd_firstRelfilenodeSubid = InvalidSubTransactionId;
3194 216876 : relation->rd_droppedSubid = InvalidSubTransactionId;
3195 :
3196 216876 : if (clear_relcache)
3197 : {
3198 2142 : if (RelationHasReferenceCountZero(relation))
3199 : {
3200 2142 : RelationClearRelation(relation, false);
3201 2142 : return;
3202 : }
3203 : else
3204 : {
3205 : /*
3206 : * Hmm, somewhere there's a (leaked?) reference to the relation.
3207 : * We daren't remove the entry for fear of dereferencing a
3208 : * dangling pointer later. Bleat, and mark it as not belonging to
3209 : * the current transaction. Hopefully it'll get cleaned up
3210 : * eventually. This must be just a WARNING to avoid
3211 : * error-during-error-recovery loops.
3212 : */
3213 0 : elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3214 : RelationGetRelationName(relation));
3215 : }
3216 : }
3217 : }
3218 :
3219 : /*
3220 : * AtEOSubXact_RelationCache
3221 : *
3222 : * Clean up the relcache at sub-transaction commit or abort.
3223 : *
3224 : * Note: this must be called *before* processing invalidation messages.
3225 : */
3226 : void
3227 8056 : AtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid,
3228 : SubTransactionId parentSubid)
3229 : {
3230 : HASH_SEQ_STATUS status;
3231 : RelIdCacheEnt *idhentry;
3232 : int i;
3233 :
3234 : /*
3235 : * Unless the eoxact_list[] overflowed, we only need to examine the rels
3236 : * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3237 : * logic as in AtEOXact_RelationCache.
3238 : */
3239 8056 : if (eoxact_list_overflowed)
3240 : {
3241 0 : hash_seq_init(&status, RelationIdCache);
3242 0 : while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3243 : {
3244 0 : AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3245 : mySubid, parentSubid);
3246 : }
3247 : }
3248 : else
3249 : {
3250 11874 : for (i = 0; i < eoxact_list_len; i++)
3251 : {
3252 3818 : idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3253 3818 : (void *) &eoxact_list[i],
3254 : HASH_FIND,
3255 : NULL);
3256 3818 : if (idhentry != NULL)
3257 3388 : AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3258 : mySubid, parentSubid);
3259 : }
3260 : }
3261 :
3262 : /* Don't reset the list; we still need more cleanup later */
3263 8056 : }
3264 :
3265 : /*
3266 : * AtEOSubXact_cleanup
3267 : *
3268 : * Clean up a single rel at subtransaction commit or abort
3269 : *
3270 : * NB: this processing must be idempotent, because EOXactListAdd() doesn't
3271 : * bother to prevent duplicate entries in eoxact_list[].
3272 : */
3273 : static void
3274 3388 : AtEOSubXact_cleanup(Relation relation, bool isCommit,
3275 : SubTransactionId mySubid, SubTransactionId parentSubid)
3276 : {
3277 : /*
3278 : * Is it a relation created in the current subtransaction?
3279 : *
3280 : * During subcommit, mark it as belonging to the parent, instead, as long
3281 : * as it has not been dropped. Otherwise simply delete the relcache entry.
3282 : * --- it isn't interesting any longer.
3283 : */
3284 3388 : if (relation->rd_createSubid == mySubid)
3285 : {
3286 : /*
3287 : * Valid rd_droppedSubid means the corresponding relation is dropped
3288 : * but the relcache entry is preserved for at-commit pending sync. We
3289 : * need to drop it explicitly here not to make the entry orphan.
3290 : */
3291 : Assert(relation->rd_droppedSubid == mySubid ||
3292 : relation->rd_droppedSubid == InvalidSubTransactionId);
3293 112 : if (isCommit && relation->rd_droppedSubid == InvalidSubTransactionId)
3294 34 : relation->rd_createSubid = parentSubid;
3295 78 : else if (RelationHasReferenceCountZero(relation))
3296 : {
3297 : /* allow the entry to be removed */
3298 78 : relation->rd_createSubid = InvalidSubTransactionId;
3299 78 : relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
3300 78 : relation->rd_firstRelfilenodeSubid = InvalidSubTransactionId;
3301 78 : relation->rd_droppedSubid = InvalidSubTransactionId;
3302 78 : RelationClearRelation(relation, false);
3303 78 : return;
3304 : }
3305 : else
3306 : {
3307 : /*
3308 : * Hmm, somewhere there's a (leaked?) reference to the relation.
3309 : * We daren't remove the entry for fear of dereferencing a
3310 : * dangling pointer later. Bleat, and transfer it to the parent
3311 : * subtransaction so we can try again later. This must be just a
3312 : * WARNING to avoid error-during-error-recovery loops.
3313 : */
3314 0 : relation->rd_createSubid = parentSubid;
3315 0 : elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3316 : RelationGetRelationName(relation));
3317 : }
3318 : }
3319 :
3320 : /*
3321 : * Likewise, update or drop any new-relfilenode-in-subtransaction record
3322 : * or drop record.
3323 : */
3324 3310 : if (relation->rd_newRelfilenodeSubid == mySubid)
3325 : {
3326 86 : if (isCommit)
3327 42 : relation->rd_newRelfilenodeSubid = parentSubid;
3328 : else
3329 44 : relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
3330 : }
3331 :
3332 3310 : if (relation->rd_firstRelfilenodeSubid == mySubid)
3333 : {
3334 62 : if (isCommit)
3335 18 : relation->rd_firstRelfilenodeSubid = parentSubid;
3336 : else
3337 44 : relation->rd_firstRelfilenodeSubid = InvalidSubTransactionId;
3338 : }
3339 :
3340 3310 : if (relation->rd_droppedSubid == mySubid)
3341 : {
3342 14 : if (isCommit)
3343 2 : relation->rd_droppedSubid = parentSubid;
3344 : else
3345 12 : relation->rd_droppedSubid = InvalidSubTransactionId;
3346 : }
3347 : }
3348 :
3349 :
3350 : /*
3351 : * RelationBuildLocalRelation
3352 : * Build a relcache entry for an about-to-be-created relation,
3353 : * and enter it into the relcache.
3354 : */
3355 : Relation
3356 206670 : RelationBuildLocalRelation(const char *relname,
3357 : Oid relnamespace,
3358 : TupleDesc tupDesc,
3359 : Oid relid,
3360 : Oid accessmtd,
3361 : Oid relfilenode,
3362 : Oid reltablespace,
3363 : bool shared_relation,
3364 : bool mapped_relation,
3365 : char relpersistence,
3366 : char relkind)
3367 : {
3368 : Relation rel;
3369 : MemoryContext oldcxt;
3370 206670 : int natts = tupDesc->natts;
3371 : int i;
3372 : bool has_not_null;
3373 : bool nailit;
3374 :
3375 : AssertArg(natts >= 0);
3376 :
3377 : /*
3378 : * check for creation of a rel that must be nailed in cache.
3379 : *
3380 : * XXX this list had better match the relations specially handled in
3381 : * RelationCacheInitializePhase2/3.
3382 : */
3383 206670 : switch (relid)
3384 : {
3385 2828 : case DatabaseRelationId:
3386 : case AuthIdRelationId:
3387 : case AuthMemRelationId:
3388 : case RelationRelationId:
3389 : case AttributeRelationId:
3390 : case ProcedureRelationId:
3391 : case TypeRelationId:
3392 2828 : nailit = true;
3393 2828 : break;
3394 203842 : default:
3395 203842 : nailit = false;
3396 203842 : break;
3397 : }
3398 :
3399 : /*
3400 : * check that hardwired list of shared rels matches what's in the
3401 : * bootstrap .bki file. If you get a failure here during initdb, you
3402 : * probably need to fix IsSharedRelation() to match whatever you've done
3403 : * to the set of shared relations.
3404 : */
3405 206670 : if (shared_relation != IsSharedRelation(relid))
3406 0 : elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3407 : relname, relid);
3408 :
3409 : /* Shared relations had better be mapped, too */
3410 : Assert(mapped_relation || !shared_relation);
3411 :
3412 : /*
3413 : * switch to the cache context to create the relcache entry.
3414 : */
3415 206670 : if (!CacheMemoryContext)
3416 0 : CreateCacheMemoryContext();
3417 :
3418 206670 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
3419 :
3420 : /*
3421 : * allocate a new relation descriptor and fill in basic state fields.
3422 : */
3423 206670 : rel = (Relation) palloc0(sizeof(RelationData));
3424 :
3425 : /* make sure relation is marked as having no open file yet */
3426 206670 : rel->rd_smgr = NULL;
3427 :
3428 : /* mark it nailed if appropriate */
3429 206670 : rel->rd_isnailed = nailit;
3430 :
3431 206670 : rel->rd_refcnt = nailit ? 1 : 0;
3432 :
3433 : /* it's being created in this transaction */
3434 206670 : rel->rd_createSubid = GetCurrentSubTransactionId();
3435 206670 : rel->rd_newRelfilenodeSubid = InvalidSubTransactionId;
3436 206670 : rel->rd_firstRelfilenodeSubid = InvalidSubTransactionId;
3437 206670 : rel->rd_droppedSubid = InvalidSubTransactionId;
3438 :
3439 : /*
3440 : * create a new tuple descriptor from the one passed in. We do this
3441 : * partly to copy it into the cache context, and partly because the new
3442 : * relation can't have any defaults or constraints yet; they have to be
3443 : * added in later steps, because they require additions to multiple system
3444 : * catalogs. We can copy attnotnull constraints here, however.
3445 : */
3446 206670 : rel->rd_att = CreateTupleDescCopy(tupDesc);
3447 206670 : rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3448 206670 : has_not_null = false;
3449 1237368 : for (i = 0; i < natts; i++)
3450 : {
3451 1030698 : Form_pg_attribute satt = TupleDescAttr(tupDesc, i);
3452 1030698 : Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i);
3453 :
3454 1030698 : datt->attidentity = satt->attidentity;
3455 1030698 : datt->attgenerated = satt->attgenerated;
3456 1030698 : datt->attnotnull = satt->attnotnull;
3457 1030698 : has_not_null |= satt->attnotnull;
3458 : }
3459 :
3460 206670 : if (has_not_null)
3461 : {
3462 32630 : TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3463 :
3464 32630 : constr->has_not_null = true;
3465 32630 : rel->rd_att->constr = constr;
3466 : }
3467 :
3468 : /*
3469 : * initialize relation tuple form (caller may add/override data later)
3470 : */
3471 206670 : rel->rd_rel = (Form_pg_class) palloc0(CLASS_TUPLE_SIZE);
3472 :
3473 206670 : namestrcpy(&rel->rd_rel->relname, relname);
3474 206670 : rel->rd_rel->relnamespace = relnamespace;
3475 :
3476 206670 : rel->rd_rel->relkind = relkind;
3477 206670 : rel->rd_rel->relnatts = natts;
3478 206670 : rel->rd_rel->reltype = InvalidOid;
3479 : /* needed when bootstrapping: */
3480 206670 : rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3481 :
3482 : /* set up persistence and relcache fields dependent on it */
3483 206670 : rel->rd_rel->relpersistence = relpersistence;
3484 206670 : switch (relpersistence)
3485 : {
3486 203324 : case RELPERSISTENCE_UNLOGGED:
3487 : case RELPERSISTENCE_PERMANENT:
3488 203324 : rel->rd_backend = InvalidBackendId;
3489 203324 : rel->rd_islocaltemp = false;
3490 203324 : break;
3491 3346 : case RELPERSISTENCE_TEMP:
3492 : Assert(isTempOrTempToastNamespace(relnamespace));
3493 3346 : rel->rd_backend = BackendIdForTempRelations();
3494 3346 : rel->rd_islocaltemp = true;
3495 3346 : break;
3496 0 : default:
3497 0 : elog(ERROR, "invalid relpersistence: %c", relpersistence);
3498 : break;
3499 : }
3500 :
3501 : /* if it's a materialized view, it's not populated initially */
3502 206670 : if (relkind == RELKIND_MATVIEW)
3503 206 : rel->rd_rel->relispopulated = false;
3504 : else
3505 206464 : rel->rd_rel->relispopulated = true;
3506 :
3507 : /* set replica identity -- system catalogs and non-tables don't have one */
3508 206670 : if (!IsCatalogNamespace(relnamespace) &&
3509 85102 : (relkind == RELKIND_RELATION ||
3510 84896 : relkind == RELKIND_MATVIEW ||
3511 : relkind == RELKIND_PARTITIONED_TABLE))
3512 23090 : rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3513 : else
3514 183580 : rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3515 :
3516 : /*
3517 : * Insert relation physical and logical identifiers (OIDs) into the right
3518 : * places. For a mapped relation, we set relfilenode to zero and rely on
3519 : * RelationInitPhysicalAddr to consult the map.
3520 : */
3521 206670 : rel->rd_rel->relisshared = shared_relation;
3522 :
3523 206670 : RelationGetRelid(rel) = relid;
3524 :
3525 1237368 : for (i = 0; i < natts; i++)
3526 1030698 : TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3527 :
3528 206670 : rel->rd_rel->reltablespace = reltablespace;
3529 :
3530 206670 : if (mapped_relation)
3531 : {
3532 24380 : rel->rd_rel->relfilenode = InvalidOid;
3533 : /* Add it to the active mapping information */
3534 24380 : RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3535 : }
3536 : else
3537 182290 : rel->rd_rel->relfilenode = relfilenode;
3538 :
3539 206670 : RelationInitLockInfo(rel); /* see lmgr.c */
3540 :
3541 206670 : RelationInitPhysicalAddr(rel);
3542 :
3543 206670 : rel->rd_rel->relam = accessmtd;
3544 :
3545 206670 : if (relkind == RELKIND_RELATION ||
3546 160076 : relkind == RELKIND_SEQUENCE ||
3547 137528 : relkind == RELKIND_TOASTVALUE ||
3548 : relkind == RELKIND_MATVIEW)
3549 69348 : RelationInitTableAccessMethod(rel);
3550 :
3551 : /*
3552 : * Okay to insert into the relcache hash table.
3553 : *
3554 : * Ordinarily, there should certainly not be an existing hash entry for
3555 : * the same OID; but during bootstrap, when we create a "real" relcache
3556 : * entry for one of the bootstrap relations, we'll be overwriting the
3557 : * phony one created with formrdesc. So allow that to happen for nailed
3558 : * rels.
3559 : */
3560 206670 : RelationCacheInsert(rel, nailit);
3561 :
3562 : /*
3563 : * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3564 : * can't do this before storing relid in it.
3565 : */
3566 206670 : EOXactListAdd(rel);
3567 :
3568 : /*
3569 : * done building relcache entry.
3570 : */
3571 206670 : MemoryContextSwitchTo(oldcxt);
3572 :
3573 : /* It's fully valid */
3574 206670 : rel->rd_isvalid = true;
3575 :
3576 : /*
3577 : * Caller expects us to pin the returned entry.
3578 : */
3579 206670 : RelationIncrementReferenceCount(rel);
3580 :
3581 206670 : return rel;
3582 : }
3583 :
3584 :
3585 : /*
3586 : * RelationSetNewRelfilenode
3587 : *
3588 : * Assign a new relfilenode (physical file name), and possibly a new
3589 : * persistence setting, to the relation.
3590 : *
3591 : * This allows a full rewrite of the relation to be done with transactional
3592 : * safety (since the filenode assignment can be rolled back). Note however
3593 : * that there is no simple way to access the relation's old data for the
3594 : * remainder of the current transaction. This limits the usefulness to cases
3595 : * such as TRUNCATE or rebuilding an index from scratch.
3596 : *
3597 : * Caller must already hold exclusive lock on the relation.
3598 : */
3599 : void
3600 9564 : RelationSetNewRelfilenode(Relation relation, char persistence)
3601 : {
3602 : Oid newrelfilenode;
3603 : Relation pg_class;
3604 : HeapTuple tuple;
3605 : Form_pg_class classform;
3606 9564 : MultiXactId minmulti = InvalidMultiXactId;
3607 9564 : TransactionId freezeXid = InvalidTransactionId;
3608 : RelFileNode newrnode;
3609 :
3610 : /* Allocate a new relfilenode */
3611 9564 : newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
3612 : persistence);
3613 :
3614 : /*
3615 : * Get a writable copy of the pg_class tuple for the given relation.
3616 : */
3617 9564 : pg_class = table_open(RelationRelationId, RowExclusiveLock);
3618 :
3619 9564 : tuple = SearchSysCacheCopy1(RELOID,
3620 : ObjectIdGetDatum(RelationGetRelid(relation)));
3621 9564 : if (!HeapTupleIsValid(tuple))
3622 0 : elog(ERROR, "could not find tuple for relation %u",
3623 : RelationGetRelid(relation));
3624 9564 : classform = (Form_pg_class) GETSTRUCT(tuple);
3625 :
3626 : /*
3627 : * Schedule unlinking of the old storage at transaction commit.
3628 : */
3629 9564 : RelationDropStorage(relation);
3630 :
3631 : /*
3632 : * Create storage for the main fork of the new relfilenode. If it's a
3633 : * table-like object, call into the table AM to do so, which'll also
3634 : * create the table's init fork if needed.
3635 : *
3636 : * NOTE: If relevant for the AM, any conflict in relfilenode value will be
3637 : * caught here, if GetNewRelFileNode messes up for any reason.
3638 : */
3639 9564 : newrnode = relation->rd_node;
3640 9564 : newrnode.relNode = newrelfilenode;
3641 :
3642 9564 : switch (relation->rd_rel->relkind)
3643 : {
3644 7204 : case RELKIND_INDEX:
3645 : case RELKIND_SEQUENCE:
3646 : {
3647 : /* handle these directly, at least for now */
3648 : SMgrRelation srel;
3649 :
3650 7204 : srel = RelationCreateStorage(newrnode, persistence);
3651 7204 : smgrclose(srel);
3652 : }
3653 7204 : break;
3654 :
3655 2360 : case RELKIND_RELATION:
3656 : case RELKIND_TOASTVALUE:
3657 : case RELKIND_MATVIEW:
3658 2360 : table_relation_set_new_filenode(relation, &newrnode,
3659 : persistence,
3660 : &freezeXid, &minmulti);
3661 2360 : break;
3662 :
3663 0 : default:
3664 : /* we shouldn't be called for anything else */
3665 0 : elog(ERROR, "relation \"%s\" does not have storage",
3666 : RelationGetRelationName(relation));
3667 : break;
3668 : }
3669 :
3670 : /*
3671 : * If we're dealing with a mapped index, pg_class.relfilenode doesn't
3672 : * change; instead we have to send the update to the relation mapper.
3673 : *
3674 : * For mapped indexes, we don't actually change the pg_class entry at all;
3675 : * this is essential when reindexing pg_class itself. That leaves us with
3676 : * possibly-inaccurate values of relpages etc, but those will be fixed up
3677 : * later.
3678 : */
3679 9564 : if (RelationIsMapped(relation))
3680 : {
3681 : /* This case is only supported for indexes */
3682 : Assert(relation->rd_rel->relkind == RELKIND_INDEX);
3683 :
3684 : /* Since we're not updating pg_class, these had better not change */
3685 : Assert(classform->relfrozenxid == freezeXid);
3686 : Assert(classform->relminmxid == minmulti);
3687 : Assert(classform->relpersistence == persistence);
3688 :
3689 : /*
3690 : * In some code paths it's possible that the tuple update we'd
3691 : * otherwise do here is the only thing that would assign an XID for
3692 : * the current transaction. However, we must have an XID to delete
3693 : * files, so make sure one is assigned.
3694 : */
3695 1228 : (void) GetCurrentTransactionId();
3696 :
3697 : /* Do the deed */
3698 1228 : RelationMapUpdateMap(RelationGetRelid(relation),
3699 : newrelfilenode,
3700 1228 : relation->rd_rel->relisshared,
3701 : false);
3702 :
3703 : /* Since we're not updating pg_class, must trigger inval manually */
3704 1228 : CacheInvalidateRelcache(relation);
3705 : }
3706 : else
3707 : {
3708 : /* Normal case, update the pg_class entry */
3709 8336 : classform->relfilenode = newrelfilenode;
3710 :
3711 : /* relpages etc. never change for sequences */
3712 8336 : if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3713 : {
3714 8218 : classform->relpages = 0; /* it's empty until further notice */
3715 8218 : classform->reltuples = -1;
3716 8218 : classform->relallvisible = 0;
3717 : }
3718 8336 : classform->relfrozenxid = freezeXid;
3719 8336 : classform->relminmxid = minmulti;
3720 8336 : classform->relpersistence = persistence;
3721 :
3722 8336 : CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3723 : }
3724 :
3725 9564 : heap_freetuple(tuple);
3726 :
3727 9564 : table_close(pg_class, RowExclusiveLock);
3728 :
3729 : /*
3730 : * Make the pg_class row change or relation map change visible. This will
3731 : * cause the relcache entry to get updated, too.
3732 : */
3733 9564 : CommandCounterIncrement();
3734 :
3735 9564 : RelationAssumeNewRelfilenode(relation);
3736 9564 : }
3737 :
3738 : /*
3739 : * RelationAssumeNewRelfilenode
3740 : *
3741 : * Code that modifies pg_class.reltablespace or pg_class.relfilenode must call
3742 : * this. The call shall precede any code that might insert WAL records whose
3743 : * replay would modify bytes in the new RelFileNode, and the call shall follow
3744 : * any WAL modifying bytes in the prior RelFileNode. See struct RelationData.
3745 : * Ideally, call this as near as possible to the CommandCounterIncrement()
3746 : * that makes the pg_class change visible (before it or after it); that
3747 : * minimizes the chance of future development adding a forbidden WAL insertion
3748 : * between RelationAssumeNewRelfilenode() and CommandCounterIncrement().
3749 : */
3750 : void
3751 10722 : RelationAssumeNewRelfilenode(Relation relation)
3752 : {
3753 10722 : relation->rd_newRelfilenodeSubid = GetCurrentSubTransactionId();
3754 10722 : if (relation->rd_firstRelfilenodeSubid == InvalidSubTransactionId)
3755 10674 : relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3756 :
3757 : /* Flag relation as needing eoxact cleanup (to clear these fields) */
3758 10722 : EOXactListAdd(relation);
3759 10722 : }
3760 :
3761 :
3762 : /*
3763 : * RelationCacheInitialize
3764 : *
3765 : * This initializes the relation descriptor cache. At the time
3766 : * that this is invoked, we can't do database access yet (mainly
3767 : * because the transaction subsystem is not up); all we are doing
3768 : * is making an empty cache hashtable. This must be done before
3769 : * starting the initialization transaction, because otherwise
3770 : * AtEOXact_RelationCache would crash if that transaction aborts
3771 : * before we can get the relcache set up.
3772 : */
3773 :
3774 : #define INITRELCACHESIZE 400
3775 :
3776 : void
3777 12482 : RelationCacheInitialize(void)
3778 : {
3779 : HASHCTL ctl;
3780 :
3781 : /*
3782 : * make sure cache memory context exists
3783 : */
3784 12482 : if (!CacheMemoryContext)
3785 12482 : CreateCacheMemoryContext();
3786 :
3787 : /*
3788 : * create hashtable that indexes the relcache
3789 : */
3790 12482 : ctl.keysize = sizeof(Oid);
3791 12482 : ctl.entrysize = sizeof(RelIdCacheEnt);
3792 12482 : RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3793 : &ctl, HASH_ELEM | HASH_BLOBS);
3794 :
3795 : /*
3796 : * relation mapper needs to be initialized too
3797 : */
3798 12482 : RelationMapInitialize();
3799 12482 : }
3800 :
3801 : /*
3802 : * RelationCacheInitializePhase2
3803 : *
3804 : * This is called to prepare for access to shared catalogs during startup.
3805 : * We must at least set up nailed reldescs for pg_database, pg_authid,
3806 : * pg_auth_members, and pg_shseclabel. Ideally we'd like to have reldescs
3807 : * for their indexes, too. We attempt to load this information from the
3808 : * shared relcache init file. If that's missing or broken, just make
3809 : * phony entries for the catalogs themselves.
3810 : * RelationCacheInitializePhase3 will clean up as needed.
3811 : */
3812 : void
3813 12482 : RelationCacheInitializePhase2(void)
3814 : {
3815 : MemoryContext oldcxt;
3816 :
3817 : /*
3818 : * relation mapper needs initialized too
3819 : */
3820 12482 : RelationMapInitializePhase2();
3821 :
3822 : /*
3823 : * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3824 : * nothing.
3825 : */
3826 12482 : if (IsBootstrapProcessingMode())
3827 404 : return;
3828 :
3829 : /*
3830 : * switch to cache memory context
3831 : */
3832 12078 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
3833 :
3834 : /*
3835 : * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3836 : * the cache with pre-made descriptors for the critical shared catalogs.
3837 : */
3838 12078 : if (!load_relcache_init_file(true))
3839 : {
3840 2210 : formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3841 : Natts_pg_database, Desc_pg_database);
3842 2210 : formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3843 : Natts_pg_authid, Desc_pg_authid);
3844 2210 : formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3845 : Natts_pg_auth_members, Desc_pg_auth_members);
3846 2210 : formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3847 : Natts_pg_shseclabel, Desc_pg_shseclabel);
3848 2210 : formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3849 : Natts_pg_subscription, Desc_pg_subscription);
3850 :
3851 : #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3852 : }
3853 :
3854 12078 : MemoryContextSwitchTo(oldcxt);
3855 : }
3856 :
3857 : /*
3858 : * RelationCacheInitializePhase3
3859 : *
3860 : * This is called as soon as the catcache and transaction system
3861 : * are functional and we have determined MyDatabaseId. At this point
3862 : * we can actually read data from the database's system catalogs.
3863 : * We first try to read pre-computed relcache entries from the local
3864 : * relcache init file. If that's missing or broken, make phony entries
3865 : * for the minimum set of nailed-in-cache relations. Then (unless
3866 : * bootstrapping) make sure we have entries for the critical system
3867 : * indexes. Once we've done all this, we have enough infrastructure to
3868 : * open any system catalog or use any catcache. The last step is to
3869 : * rewrite the cache files if needed.
3870 : */
3871 : void
3872 11168 : RelationCacheInitializePhase3(void)
3873 : {
3874 : HASH_SEQ_STATUS status;
3875 : RelIdCacheEnt *idhentry;
3876 : MemoryContext oldcxt;
3877 11168 : bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3878 :
3879 : /*
3880 : * relation mapper needs initialized too
3881 : */
3882 11168 : RelationMapInitializePhase3();
3883 :
3884 : /*
3885 : * switch to cache memory context
3886 : */
3887 11168 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
3888 :
3889 : /*
3890 : * Try to load the local relcache cache file. If unsuccessful, bootstrap
3891 : * the cache with pre-made descriptors for the critical "nailed-in" system
3892 : * catalogs.
3893 : */
3894 11168 : if (IsBootstrapProcessingMode() ||
3895 10764 : !load_relcache_init_file(false))
3896 : {
3897 1936 : needNewCacheFile = true;
3898 :
3899 1936 : formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3900 : Natts_pg_class, Desc_pg_class);
3901 1936 : formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3902 : Natts_pg_attribute, Desc_pg_attribute);
3903 1936 : formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3904 : Natts_pg_proc, Desc_pg_proc);
3905 1936 : formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3906 : Natts_pg_type, Desc_pg_type);
3907 :
3908 : #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3909 : }
3910 :
3911 11168 : MemoryContextSwitchTo(oldcxt);
3912 :
3913 : /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3914 11168 : if (IsBootstrapProcessingMode())
3915 404 : return;
3916 :
3917 : /*
3918 : * If we didn't get the critical system indexes loaded into relcache, do
3919 : * so now. These are critical because the catcache and/or opclass cache
3920 : * depend on them for fetches done during relcache load. Thus, we have an
3921 : * infinite-recursion problem. We can break the recursion by doing
3922 : * heapscans instead of indexscans at certain key spots. To avoid hobbling
3923 : * performance, we only want to do that until we have the critical indexes
3924 : * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3925 : * decide whether to do heapscan or indexscan at the key spots, and we set
3926 : * it true after we've loaded the critical indexes.
3927 : *
3928 : * The critical indexes are marked as "nailed in cache", partly to make it
3929 : * easy for load_relcache_init_file to count them, but mainly because we
3930 : * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3931 : * true. (NOTE: perhaps it would be possible to reload them by
3932 : * temporarily setting criticalRelcachesBuilt to false again. For now,
3933 : * though, we just nail 'em in.)
3934 : *
3935 : * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3936 : * in the same way as the others, because the critical catalogs don't
3937 : * (currently) have any rules or triggers, and so these indexes can be
3938 : * rebuilt without inducing recursion. However they are used during
3939 : * relcache load when a rel does have rules or triggers, so we choose to
3940 : * nail them for performance reasons.
3941 : */
3942 10764 : if (!criticalRelcachesBuilt)
3943 : {
3944 1532 : load_critical_index(ClassOidIndexId,
3945 : RelationRelationId);
3946 1532 : load_critical_index(AttributeRelidNumIndexId,
3947 : AttributeRelationId);
3948 1532 : load_critical_index(IndexRelidIndexId,
3949 : IndexRelationId);
3950 1532 : load_critical_index(OpclassOidIndexId,
3951 : OperatorClassRelationId);
3952 1532 : load_critical_index(AccessMethodProcedureIndexId,
3953 : AccessMethodProcedureRelationId);
3954 1532 : load_critical_index(RewriteRelRulenameIndexId,
3955 : RewriteRelationId);
3956 1532 : load_critical_index(TriggerRelidNameIndexId,
3957 : TriggerRelationId);
3958 :
3959 : #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3960 :
3961 1532 : criticalRelcachesBuilt = true;
3962 : }
3963 :
3964 : /*
3965 : * Process critical shared indexes too.
3966 : *
3967 : * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3968 : * initial lookup of MyDatabaseId, without which we'll never find any
3969 : * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3970 : * database OID, so it instead depends on DatabaseOidIndexId. We also
3971 : * need to nail up some indexes on pg_authid and pg_auth_members for use
3972 : * during client authentication. SharedSecLabelObjectIndexId isn't
3973 : * critical for the core system, but authentication hooks might be
3974 : * interested in it.
3975 : */
3976 10764 : if (!criticalSharedRelcachesBuilt)
3977 : {
3978 1252 : load_critical_index(DatabaseNameIndexId,
3979 : DatabaseRelationId);
3980 1252 : load_critical_index(DatabaseOidIndexId,
3981 : DatabaseRelationId);
3982 1252 : load_critical_index(AuthIdRolnameIndexId,
3983 : AuthIdRelationId);
3984 1252 : load_critical_index(AuthIdOidIndexId,
3985 : AuthIdRelationId);
3986 1252 : load_critical_index(AuthMemMemRoleIndexId,
3987 : AuthMemRelationId);
3988 1252 : load_critical_index(SharedSecLabelObjectIndexId,
3989 : SharedSecLabelRelationId);
3990 :
3991 : #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3992 :
3993 1252 : criticalSharedRelcachesBuilt = true;
3994 : }
3995 :
3996 : /*
3997 : * Now, scan all the relcache entries and update anything that might be
3998 : * wrong in the results from formrdesc or the relcache cache file. If we
3999 : * faked up relcache entries using formrdesc, then read the real pg_class
4000 : * rows and replace the fake entries with them. Also, if any of the
4001 : * relcache entries have rules, triggers, or security policies, load that
4002 : * info the hard way since it isn't recorded in the cache file.
4003 : *
4004 : * Whenever we access the catalogs to read data, there is a possibility of
4005 : * a shared-inval cache flush causing relcache entries to be removed.
4006 : * Since hash_seq_search only guarantees to still work after the *current*
4007 : * entry is removed, it's unsafe to continue the hashtable scan afterward.
4008 : * We handle this by restarting the scan from scratch after each access.
4009 : * This is theoretically O(N^2), but the number of entries that actually
4010 : * need to be fixed is small enough that it doesn't matter.
4011 : */
4012 10764 : hash_seq_init(&status, RelationIdCache);
4013 :
4014 1438908 : while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
4015 : {
4016 1428144 : Relation relation = idhentry->reldesc;
4017 1428144 : bool restart = false;
4018 :
4019 : /*
4020 : * Make sure *this* entry doesn't get flushed while we work with it.
4021 : */
4022 1428144 : RelationIncrementReferenceCount(relation);
4023 :
4024 : /*
4025 : * If it's a faked-up entry, read the real pg_class tuple.
4026 : */
4027 1428144 : if (relation->rd_rel->relowner == InvalidOid)
4028 : {
4029 : HeapTuple htup;
4030 : Form_pg_class relp;
4031 :
4032 12388 : htup = SearchSysCache1(RELOID,
4033 12388 : ObjectIdGetDatum(RelationGetRelid(relation)));
4034 12388 : if (!HeapTupleIsValid(htup))
4035 0 : elog(FATAL, "cache lookup failed for relation %u",
4036 : RelationGetRelid(relation));
4037 12388 : relp = (Form_pg_class) GETSTRUCT(htup);
4038 :
4039 : /*
4040 : * Copy tuple to relation->rd_rel. (See notes in
4041 : * AllocateRelationDesc())
4042 : */
4043 12388 : memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
4044 :
4045 : /* Update rd_options while we have the tuple */
4046 12388 : if (relation->rd_options)
4047 0 : pfree(relation->rd_options);
4048 12388 : RelationParseRelOptions(relation, htup);
4049 :
4050 : /*
4051 : * Check the values in rd_att were set up correctly. (We cannot
4052 : * just copy them over now: formrdesc must have set up the rd_att
4053 : * data correctly to start with, because it may already have been
4054 : * copied into one or more catcache entries.)
4055 : */
4056 : Assert(relation->rd_att->tdtypeid == relp->reltype);
4057 : Assert(relation->rd_att->tdtypmod == -1);
4058 :
4059 12388 : ReleaseSysCache(htup);
4060 :
4061 : /* relowner had better be OK now, else we'll loop forever */
4062 12388 : if (relation->rd_rel->relowner == InvalidOid)
4063 0 : elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
4064 : RelationGetRelationName(relation));
4065 :
4066 12388 : restart = true;
4067 : }
4068 :
4069 : /*
4070 : * Fix data that isn't saved in relcache cache file.
4071 : *
4072 : * relhasrules or relhastriggers could possibly be wrong or out of
4073 : * date. If we don't actually find any rules or triggers, clear the
4074 : * local copy of the flag so that we don't get into an infinite loop
4075 : * here. We don't make any attempt to fix the pg_class entry, though.
4076 : */
4077 1428144 : if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
4078 : {
4079 0 : RelationBuildRuleLock(relation);
4080 0 : if (relation->rd_rules == NULL)
4081 0 : relation->rd_rel->relhasrules = false;
4082 0 : restart = true;
4083 : }
4084 1428144 : if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
4085 : {
4086 0 : RelationBuildTriggers(relation);
4087 0 : if (relation->trigdesc == NULL)
4088 0 : relation->rd_rel->relhastriggers = false;
4089 0 : restart = true;
4090 : }
4091 :
4092 : /*
4093 : * Re-load the row security policies if the relation has them, since
4094 : * they are not preserved in the cache. Note that we can never NOT
4095 : * have a policy while relrowsecurity is true,
4096 : * RelationBuildRowSecurity will create a single default-deny policy
4097 : * if there is no policy defined in pg_policy.
4098 : */
4099 1428144 : if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
4100 : {
4101 0 : RelationBuildRowSecurity(relation);
4102 :
4103 : Assert(relation->rd_rsdesc != NULL);
4104 0 : restart = true;
4105 : }
4106 :
4107 : /* Reload tableam data if needed */
4108 1428144 : if (relation->rd_tableam == NULL &&
4109 859000 : (relation->rd_rel->relkind == RELKIND_RELATION ||
4110 859000 : relation->rd_rel->relkind == RELKIND_SEQUENCE ||
4111 859000 : relation->rd_rel->relkind == RELKIND_TOASTVALUE ||
4112 859000 : relation->rd_rel->relkind == RELKIND_MATVIEW))
4113 : {
4114 0 : RelationInitTableAccessMethod(relation);
4115 : Assert(relation->rd_tableam != NULL);
4116 :
4117 0 : restart = true;
4118 : }
4119 :
4120 : /* Release hold on the relation */
4121 1428144 : RelationDecrementReferenceCount(relation);
4122 :
4123 : /* Now, restart the hashtable scan if needed */
4124 1428144 : if (restart)
4125 : {
4126 12388 : hash_seq_term(&status);
4127 12388 : hash_seq_init(&status, RelationIdCache);
4128 : }
4129 : }
4130 :
4131 : /*
4132 : * Lastly, write out new relcache cache files if needed. We don't bother
4133 : * to distinguish cases where only one of the two needs an update.
4134 : */
4135 10764 : if (needNewCacheFile)
4136 : {
4137 : /*
4138 : * Force all the catcaches to finish initializing and thereby open the
4139 : * catalogs and indexes they use. This will preload the relcache with
4140 : * entries for all the most important system catalogs and indexes, so
4141 : * that the init files will be most useful for future backends.
4142 : */
4143 1548 : InitCatalogCachePhase2();
4144 :
4145 : /* now write the files */
4146 1548 : write_relcache_init_file(true);
4147 1548 : write_relcache_init_file(false);
4148 : }
4149 : }
4150 :
4151 : /*
4152 : * Load one critical system index into the relcache
4153 : *
4154 : * indexoid is the OID of the target index, heapoid is the OID of the catalog
4155 : * it belongs to.
4156 : */
4157 : static void
4158 18236 : load_critical_index(Oid indexoid, Oid heapoid)
4159 : {
4160 : Relation ird;
4161 :
4162 : /*
4163 : * We must lock the underlying catalog before locking the index to avoid
4164 : * deadlock, since RelationBuildDesc might well need to read the catalog,
4165 : * and if anyone else is exclusive-locking this catalog and index they'll
4166 : * be doing it in that order.
4167 : */
4168 18236 : LockRelationOid(heapoid, AccessShareLock);
4169 18236 : LockRelationOid(indexoid, AccessShareLock);
4170 18236 : ird = RelationBuildDesc(indexoid, true);
4171 18236 : if (ird == NULL)
4172 0 : elog(PANIC, "could not open critical system index %u", indexoid);
4173 18236 : ird->rd_isnailed = true;
4174 18236 : ird->rd_refcnt = 1;
4175 18236 : UnlockRelationOid(indexoid, AccessShareLock);
4176 18236 : UnlockRelationOid(heapoid, AccessShareLock);
4177 :
4178 18236 : (void) RelationGetIndexAttOptions(ird, false);
4179 18236 : }
4180 :
4181 : /*
4182 : * GetPgClassDescriptor -- get a predefined tuple descriptor for pg_class
4183 : * GetPgIndexDescriptor -- get a predefined tuple descriptor for pg_index
4184 : *
4185 : * We need this kluge because we have to be able to access non-fixed-width
4186 : * fields of pg_class and pg_index before we have the standard catalog caches
4187 : * available. We use predefined data that's set up in just the same way as
4188 : * the bootstrapped reldescs used by formrdesc(). The resulting tupdesc is
4189 : * not 100% kosher: it does not have the correct rowtype OID in tdtypeid, nor
4190 : * does it have a TupleConstr field. But it's good enough for the purpose of
4191 : * extracting fields.
4192 : */
4193 : static TupleDesc
4194 22336 : BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
4195 : {
4196 : TupleDesc result;
4197 : MemoryContext oldcxt;
4198 : int i;
4199 :
4200 22336 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
4201 :
4202 22336 : result = CreateTemplateTupleDesc(natts);
4203 22336 : result->tdtypeid = RECORDOID; /* not right, but we don't care */
4204 22336 : result->tdtypmod = -1;
4205 :
4206 614240 : for (i = 0; i < natts; i++)
4207 : {
4208 591904 : memcpy(TupleDescAttr(result, i), &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
4209 : /* make sure attcacheoff is valid */
4210 591904 : TupleDescAttr(result, i)->attcacheoff = -1;
4211 : }
4212 :
4213 : /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
4214 22336 : TupleDescAttr(result, 0)->attcacheoff = 0;
4215 :
4216 : /* Note: we don't bother to set up a TupleConstr entry */
4217 :
4218 22336 : MemoryContextSwitchTo(oldcxt);
4219 :
4220 22336 : return result;
4221 : }
4222 :
4223 : static TupleDesc
4224 938052 : GetPgClassDescriptor(void)
4225 : {
4226 : static TupleDesc pgclassdesc = NULL;
4227 :
4228 : /* Already done? */
4229 938052 : if (pgclassdesc == NULL)
4230 11168 : pgclassdesc = BuildHardcodedDescriptor(Natts_pg_class,
4231 : Desc_pg_class);
4232 :
4233 938052 : return pgclassdesc;
4234 : }
4235 :
4236 : static TupleDesc
4237 1050286 : GetPgIndexDescriptor(void)
4238 : {
4239 : static TupleDesc pgindexdesc = NULL;
4240 :
4241 : /* Already done? */
4242 1050286 : if (pgindexdesc == NULL)
4243 11168 : pgindexdesc = BuildHardcodedDescriptor(Natts_pg_index,
4244 : Desc_pg_index);
4245 :
4246 1050286 : return pgindexdesc;
4247 : }
4248 :
4249 : /*
4250 : * Load any default attribute value definitions for the relation.
4251 : */
4252 : static void
4253 13850 : AttrDefaultFetch(Relation relation)
4254 : {
4255 13850 : AttrDefault *attrdef = relation->rd_att->constr->defval;
4256 13850 : int ndef = relation->rd_att->constr->num_defval;
4257 : Relation adrel;
4258 : SysScanDesc adscan;
4259 : ScanKeyData skey;
4260 : HeapTuple htup;
4261 : Datum val;
4262 : bool isnull;
4263 : int found;
4264 : int i;
4265 :
4266 13850 : ScanKeyInit(&skey,
4267 : Anum_pg_attrdef_adrelid,
4268 : BTEqualStrategyNumber, F_OIDEQ,
4269 13850 : ObjectIdGetDatum(RelationGetRelid(relation)));
4270 :
4271 13850 : adrel = table_open(AttrDefaultRelationId, AccessShareLock);
4272 13850 : adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4273 : NULL, 1, &skey);
4274 13850 : found = 0;
4275 :
4276 33814 : while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4277 : {
4278 19964 : Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4279 19964 : Form_pg_attribute attr = TupleDescAttr(relation->rd_att, adform->adnum - 1);
4280 :
4281 36940 : for (i = 0; i < ndef; i++)
4282 : {
4283 36940 : if (adform->adnum != attrdef[i].adnum)
4284 16976 : continue;
4285 19964 : if (attrdef[i].adbin != NULL)
4286 0 : elog(WARNING, "multiple attrdef records found for attr %s of rel %s",
4287 : NameStr(attr->attname),
4288 : RelationGetRelationName(relation));
4289 : else
4290 19964 : found++;
4291 :
4292 19964 : val = fastgetattr(htup,
4293 : Anum_pg_attrdef_adbin,
4294 : adrel->rd_att, &isnull);
4295 19964 : if (isnull)
4296 0 : elog(WARNING, "null adbin for attr %s of rel %s",
4297 : NameStr(attr->attname),
4298 : RelationGetRelationName(relation));
4299 : else
4300 : {
4301 : /* detoast and convert to cstring in caller's context */
4302 19964 : char *s = TextDatumGetCString(val);
4303 :
4304 19964 : attrdef[i].adbin = MemoryContextStrdup(CacheMemoryContext, s);
4305 19964 : pfree(s);
4306 : }
4307 19964 : break;
4308 : }
4309 :
4310 19964 : if (i >= ndef)
4311 0 : elog(WARNING, "unexpected attrdef record found for attr %d of rel %s",
4312 : adform->adnum, RelationGetRelationName(relation));
4313 : }
4314 :
4315 13850 : systable_endscan(adscan);
4316 13850 : table_close(adrel, AccessShareLock);
4317 13850 : }
4318 :
4319 : /*
4320 : * Load any check constraints for the relation.
4321 : */
4322 : static void
4323 5640 : CheckConstraintFetch(Relation relation)
4324 : {
4325 5640 : ConstrCheck *check = relation->rd_att->constr->check;
4326 5640 : int ncheck = relation->rd_att->constr->num_check;
4327 : Relation conrel;
4328 : SysScanDesc conscan;
4329 : ScanKeyData skey[1];
4330 : HeapTuple htup;
4331 5640 : int found = 0;
4332 :
4333 5640 : ScanKeyInit(&skey[0],
4334 : Anum_pg_constraint_conrelid,
4335 : BTEqualStrategyNumber, F_OIDEQ,
4336 5640 : ObjectIdGetDatum(RelationGetRelid(relation)));
4337 :
4338 5640 : conrel = table_open(ConstraintRelationId, AccessShareLock);
4339 5640 : conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4340 : NULL, 1, skey);
4341 :
4342 14524 : while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4343 : {
4344 8884 : Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(htup);
4345 : Datum val;
4346 : bool isnull;
4347 : char *s;
4348 :
4349 : /* We want check constraints only */
4350 8884 : if (conform->contype != CONSTRAINT_CHECK)
4351 1366 : continue;
4352 :
4353 7518 : if (found >= ncheck)
4354 0 : elog(ERROR, "unexpected constraint record found for rel %s",
4355 : RelationGetRelationName(relation));
4356 :
4357 7518 : check[found].ccvalid = conform->convalidated;
4358 7518 : check[found].ccnoinherit = conform->connoinherit;
4359 15036 : check[found].ccname = MemoryContextStrdup(CacheMemoryContext,
4360 7518 : NameStr(conform->conname));
4361 :
4362 : /* Grab and test conbin is actually set */
4363 7518 : val = fastgetattr(htup,
4364 : Anum_pg_constraint_conbin,
4365 : conrel->rd_att, &isnull);
4366 7518 : if (isnull)
4367 0 : elog(ERROR, "null conbin for rel %s",
4368 : RelationGetRelationName(relation));
4369 :
4370 : /* detoast and convert to cstring in caller's context */
4371 7518 : s = TextDatumGetCString(val);
4372 7518 : check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4373 7518 : pfree(s);
4374 :
4375 7518 : found++;
4376 : }
4377 :
4378 5640 : systable_endscan(conscan);
4379 5640 : table_close(conrel, AccessShareLock);
4380 :
4381 5640 : if (found != ncheck)
4382 0 : elog(ERROR, "%d constraint record(s) missing for rel %s",
4383 : ncheck - found, RelationGetRelationName(relation));
4384 :
4385 : /* Sort the records so that CHECKs are applied in a deterministic order */
4386 5640 : if (ncheck > 1)
4387 1562 : qsort(check, ncheck, sizeof(ConstrCheck), CheckConstraintCmp);
4388 5640 : }
4389 :
4390 : /*
4391 : * qsort comparator to sort ConstrCheck entries by name
4392 : */
4393 : static int
4394 1878 : CheckConstraintCmp(const void *a, const void *b)
4395 : {
4396 1878 : const ConstrCheck *ca = (const ConstrCheck *) a;
4397 1878 : const ConstrCheck *cb = (const ConstrCheck *) b;
4398 :
4399 1878 : return strcmp(ca->ccname, cb->ccname);
4400 : }
4401 :
4402 : /*
4403 : * RelationGetFKeyList -- get a list of foreign key info for the relation
4404 : *
4405 : * Returns a list of ForeignKeyCacheInfo structs, one per FK constraining
4406 : * the given relation. This data is a direct copy of relevant fields from
4407 : * pg_constraint. The list items are in no particular order.
4408 : *
4409 : * CAUTION: the returned list is part of the relcache's data, and could
4410 : * vanish in a relcache entry reset. Callers must inspect or copy it
4411 : * before doing anything that might trigger a cache flush, such as
4412 : * system catalog accesses. copyObject() can be used if desired.
4413 : * (We define it this way because current callers want to filter and
4414 : * modify the list entries anyway, so copying would be a waste of time.)
4415 : */
4416 : List *
4417 133828 : RelationGetFKeyList(Relation relation)
4418 : {
4419 : List *result;
4420 : Relation conrel;
4421 : SysScanDesc conscan;
4422 : ScanKeyData skey;
4423 : HeapTuple htup;
4424 : List *oldlist;
4425 : MemoryContext oldcxt;
4426 :
4427 : /* Quick exit if we already computed the list. */
4428 133828 : if (relation->rd_fkeyvalid)
4429 862 : return relation->rd_fkeylist;
4430 :
4431 : /* Fast path: non-partitioned tables without triggers can't have FKs */
4432 132966 : if (!relation->rd_rel->relhastriggers &&
4433 130972 : relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
4434 125918 : return NIL;
4435 :
4436 : /*
4437 : * We build the list we intend to return (in the caller's context) while
4438 : * doing the scan. After successfully completing the scan, we copy that
4439 : * list into the relcache entry. This avoids cache-context memory leakage
4440 : * if we get some sort of error partway through.
4441 : */
4442 7048 : result = NIL;
4443 :
4444 : /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4445 7048 : ScanKeyInit(&skey,
4446 : Anum_pg_constraint_conrelid,
4447 : BTEqualStrategyNumber, F_OIDEQ,
4448 7048 : ObjectIdGetDatum(RelationGetRelid(relation)));
4449 :
4450 7048 : conrel = table_open(ConstraintRelationId, AccessShareLock);
4451 7048 : conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4452 : NULL, 1, &skey);
4453 :
4454 10406 : while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4455 : {
4456 3358 : Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4457 : ForeignKeyCacheInfo *info;
4458 :
4459 : /* consider only foreign keys */
4460 3358 : if (constraint->contype != CONSTRAINT_FOREIGN)
4461 1504 : continue;
4462 :
4463 1854 : info = makeNode(ForeignKeyCacheInfo);
4464 1854 : info->conoid = constraint->oid;
4465 1854 : info->conrelid = constraint->conrelid;
4466 1854 : info->confrelid = constraint->confrelid;
4467 :
4468 1854 : DeconstructFkConstraintRow(htup, &info->nkeys,
4469 1854 : info->conkey,
4470 1854 : info->confkey,
4471 1854 : info->conpfeqop,
4472 : NULL, NULL);
4473 :
4474 : /* Add FK's node to the result list */
4475 1854 : result = lappend(result, info);
4476 : }
4477 :
4478 7048 : systable_endscan(conscan);
4479 7048 : table_close(conrel, AccessShareLock);
4480 :
4481 : /* Now save a copy of the completed list in the relcache entry. */
4482 7048 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
4483 7048 : oldlist = relation->rd_fkeylist;
4484 7048 : relation->rd_fkeylist = copyObject(result);
4485 7048 : relation->rd_fkeyvalid = true;
4486 7048 : MemoryContextSwitchTo(oldcxt);
4487 :
4488 : /* Don't leak the old list, if there is one */
4489 7048 : list_free_deep(oldlist);
4490 :
4491 7048 : return result;
4492 : }
4493 :
4494 : /*
4495 : * RelationGetIndexList -- get a list of OIDs of indexes on this relation
4496 : *
4497 : * The index list is created only if someone requests it. We scan pg_index
4498 : * to find relevant indexes, and add the list to the relcache entry so that
4499 : * we won't have to compute it again. Note that shared cache inval of a
4500 : * relcache entry will delete the old list and set rd_indexvalid to false,
4501 : * so that we must recompute the index list on next request. This handles
4502 : * creation or deletion of an index.
4503 : *
4504 : * Indexes that are marked not indislive are omitted from the returned list.
4505 : * Such indexes are expected to be dropped momentarily, and should not be
4506 : * touched at all by any caller of this function.
4507 : *
4508 : * The returned list is guaranteed to be sorted in order by OID. This is
4509 : * needed by the executor, since for index types that we obtain exclusive
4510 : * locks on when updating the index, all backends must lock the indexes in
4511 : * the same order or we will get deadlocks (see ExecOpenIndices()). Any
4512 : * consistent ordering would do, but ordering by OID is easy.
4513 : *
4514 : * Since shared cache inval causes the relcache's copy of the list to go away,
4515 : * we return a copy of the list palloc'd in the caller's context. The caller
4516 : * may list_free() the returned list after scanning it. This is necessary
4517 : * since the caller will typically be doing syscache lookups on the relevant
4518 : * indexes, and syscache lookup could cause SI messages to be processed!
4519 : *
4520 : * In exactly the same way, we update rd_pkindex, which is the OID of the
4521 : * relation's primary key index if any, else InvalidOid; and rd_replidindex,
4522 : * which is the pg_class OID of an index to be used as the relation's
4523 : * replication identity index, or InvalidOid if there is no such index.
4524 : */
4525 : List *
4526 2675526 : RelationGetIndexList(Relation relation)
4527 : {
4528 : Relation indrel;
4529 : SysScanDesc indscan;
4530 : ScanKeyData skey;
4531 : HeapTuple htup;
4532 : List *result;
4533 : List *oldlist;
4534 2675526 : char replident = relation->rd_rel->relreplident;
4535 2675526 : Oid pkeyIndex = InvalidOid;
4536 2675526 : Oid candidateIndex = InvalidOid;
4537 : MemoryContext oldcxt;
4538 :
4539 : /* Quick exit if we already computed the list. */
4540 2675526 : if (relation->rd_indexvalid)
4541 2528236 : return list_copy(relation->rd_indexlist);
4542 :
4543 : /*
4544 : * We build the list we intend to return (in the caller's context) while
4545 : * doing the scan. After successfully completing the scan, we copy that
4546 : * list into the relcache entry. This avoids cache-context memory leakage
4547 : * if we get some sort of error partway through.
4548 : */
4549 147290 : result = NIL;
4550 :
4551 : /* Prepare to scan pg_index for entries having indrelid = this rel. */
4552 147290 : ScanKeyInit(&skey,
4553 : Anum_pg_index_indrelid,
4554 : BTEqualStrategyNumber, F_OIDEQ,
4555 147290 : ObjectIdGetDatum(RelationGetRelid(relation)));
4556 :
4557 147290 : indrel = table_open(IndexRelationId, AccessShareLock);
4558 147290 : indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4559 : NULL, 1, &skey);
4560 :
4561 368186 : while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4562 : {
4563 220896 : Form_pg_index index = (Form_pg_index) GETSTRUCT(htup);
4564 :
4565 : /*
4566 : * Ignore any indexes that are currently being dropped. This will
4567 : * prevent them from being searched, inserted into, or considered in
4568 : * HOT-safety decisions. It's unsafe to touch such an index at all
4569 : * since its catalog entries could disappear at any instant.
4570 : */
4571 220896 : if (!index->indislive)
4572 0 : continue;
4573 :
4574 : /* add index's OID to result list */
4575 220896 : result = lappend_oid(result, index->indexrelid);
4576 :
4577 : /*
4578 : * Invalid, non-unique, non-immediate or predicate indexes aren't
4579 : * interesting for either oid indexes or replication identity indexes,
4580 : * so don't check them.
4581 : */
4582 220896 : if (!index->indisvalid || !index->indisunique ||
4583 183724 : !index->indimmediate ||
4584 183666 : !heap_attisnull(htup, Anum_pg_index_indpred, NULL))
4585 37310 : continue;
4586 :
4587 : /* remember primary key index if any */
4588 183586 : if (index->indisprimary)
4589 37558 : pkeyIndex = index->indexrelid;
4590 :
4591 : /* remember explicitly chosen replica index */
4592 183586 : if (index->indisreplident)
4593 10 : candidateIndex = index->indexrelid;
4594 : }
4595 :
4596 147290 : systable_endscan(indscan);
4597 :
4598 147290 : table_close(indrel, AccessShareLock);
4599 :
4600 : /* Sort the result list into OID order, per API spec. */
4601 147290 : list_sort(result, list_oid_cmp);
4602 :
4603 : /* Now save a copy of the completed list in the relcache entry. */
4604 147290 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
4605 147290 : oldlist = relation->rd_indexlist;
4606 147290 : relation->rd_indexlist = list_copy(result);
4607 147290 : relation->rd_pkindex = pkeyIndex;
4608 147290 : if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4609 14784 : relation->rd_replidindex = pkeyIndex;
4610 132506 : else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4611 10 : relation->rd_replidindex = candidateIndex;
4612 : else
4613 132496 : relation->rd_replidindex = InvalidOid;
4614 147290 : relation->rd_indexvalid = true;
4615 147290 : MemoryContextSwitchTo(oldcxt);
4616 :
4617 : /* Don't leak the old list, if there is one */
4618 147290 : list_free(oldlist);
4619 :
4620 147290 : return result;
4621 : }
4622 :
4623 : /*
4624 : * RelationGetStatExtList
4625 : * get a list of OIDs of statistics objects on this relation
4626 : *
4627 : * The statistics list is created only if someone requests it, in a way
4628 : * similar to RelationGetIndexList(). We scan pg_statistic_ext to find
4629 : * relevant statistics, and add the list to the relcache entry so that we
4630 : * won't have to compute it again. Note that shared cache inval of a
4631 : * relcache entry will delete the old list and set rd_statvalid to 0,
4632 : * so that we must recompute the statistics list on next request. This
4633 : * handles creation or deletion of a statistics object.
4634 : *
4635 : * The returned list is guaranteed to be sorted in order by OID, although
4636 : * this is not currently needed.
4637 : *
4638 : * Since shared cache inval causes the relcache's copy of the list to go away,
4639 : * we return a copy of the list palloc'd in the caller's context. The caller
4640 : * may list_free() the returned list after scanning it. This is necessary
4641 : * since the caller will typically be doing syscache lookups on the relevant
4642 : * statistics, and syscache lookup could cause SI messages to be processed!
4643 : */
4644 : List *
4645 286468 : RelationGetStatExtList(Relation relation)
4646 : {
4647 : Relation indrel;
4648 : SysScanDesc indscan;
4649 : ScanKeyData skey;
4650 : HeapTuple htup;
4651 : List *result;
4652 : List *oldlist;
4653 : MemoryContext oldcxt;
4654 :
4655 : /* Quick exit if we already computed the list. */
4656 286468 : if (relation->rd_statvalid != 0)
4657 213596 : return list_copy(relation->rd_statlist);
4658 :
4659 : /*
4660 : * We build the list we intend to return (in the caller's context) while
4661 : * doing the scan. After successfully completing the scan, we copy that
4662 : * list into the relcache entry. This avoids cache-context memory leakage
4663 : * if we get some sort of error partway through.
4664 : */
4665 72872 : result = NIL;
4666 :
4667 : /*
4668 : * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4669 : * rel.
4670 : */
4671 72872 : ScanKeyInit(&skey,
4672 : Anum_pg_statistic_ext_stxrelid,
4673 : BTEqualStrategyNumber, F_OIDEQ,
4674 72872 : ObjectIdGetDatum(RelationGetRelid(relation)));
4675 :
4676 72872 : indrel = table_open(StatisticExtRelationId, AccessShareLock);
4677 72872 : indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4678 : NULL, 1, &skey);
4679 :
4680 72976 : while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4681 : {
4682 104 : Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
4683 :
4684 104 : result = lappend_oid(result, oid);
4685 : }
4686 :
4687 72872 : systable_endscan(indscan);
4688 :
4689 72872 : table_close(indrel, AccessShareLock);
4690 :
4691 : /* Sort the result list into OID order, per API spec. */
4692 72872 : list_sort(result, list_oid_cmp);
4693 :
4694 : /* Now save a copy of the completed list in the relcache entry. */
4695 72872 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
4696 72872 : oldlist = relation->rd_statlist;
4697 72872 : relation->rd_statlist = list_copy(result);
4698 :
4699 72872 : relation->rd_statvalid = true;
4700 72872 : MemoryContextSwitchTo(oldcxt);
4701 :
4702 : /* Don't leak the old list, if there is one */
4703 72872 : list_free(oldlist);
4704 :
4705 72872 : return result;
4706 : }
4707 :
4708 : /*
4709 : * RelationGetPrimaryKeyIndex -- get OID of the relation's primary key index
4710 : *
4711 : * Returns InvalidOid if there is no such index.
4712 : */
4713 : Oid
4714 246 : RelationGetPrimaryKeyIndex(Relation relation)
4715 : {
4716 : List *ilist;
4717 :
4718 246 : if (!relation->rd_indexvalid)
4719 : {
4720 : /* RelationGetIndexList does the heavy lifting. */
4721 0 : ilist = RelationGetIndexList(relation);
4722 0 : list_free(ilist);
4723 : Assert(relation->rd_indexvalid);
4724 : }
4725 :
4726 246 : return relation->rd_pkindex;
4727 : }
4728 :
4729 : /*
4730 : * RelationGetReplicaIndex -- get OID of the relation's replica identity index
4731 : *
4732 : * Returns InvalidOid if there is no such index.
4733 : */
4734 : Oid
4735 123040 : RelationGetReplicaIndex(Relation relation)
4736 : {
4737 : List *ilist;
4738 :
4739 123040 : if (!relation->rd_indexvalid)
4740 : {
4741 : /* RelationGetIndexList does the heavy lifting. */
4742 3192 : ilist = RelationGetIndexList(relation);
4743 3192 : list_free(ilist);
4744 : Assert(relation->rd_indexvalid);
4745 : }
4746 :
4747 123040 : return relation->rd_replidindex;
4748 : }
4749 :
4750 : /*
4751 : * RelationGetIndexExpressions -- get the index expressions for an index
4752 : *
4753 : * We cache the result of transforming pg_index.indexprs into a node tree.
4754 : * If the rel is not an index or has no expressional columns, we return NIL.
4755 : * Otherwise, the returned tree is copied into the caller's memory context.
4756 : * (We don't want to return a pointer to the relcache copy, since it could
4757 : * disappear due to relcache invalidation.)
4758 : */
4759 : List *
4760 5004272 : RelationGetIndexExpressions(Relation relation)
4761 : {
4762 : List *result;
4763 : Datum exprsDatum;
4764 : bool isnull;
4765 : char *exprsString;
4766 : MemoryContext oldcxt;
4767 :
4768 : /* Quick exit if we already computed the result. */
4769 5004272 : if (relation->rd_indexprs)
4770 1738 : return copyObject(relation->rd_indexprs);
4771 :
4772 : /* Quick exit if there is nothing to do. */
4773 10005068 : if (relation->rd_indextuple == NULL ||
4774 5002534 : heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4775 5001812 : return NIL;
4776 :
4777 : /*
4778 : * We build the tree we intend to return in the caller's context. After
4779 : * successfully completing the work, we copy it into the relcache entry.
4780 : * This avoids problems if we get some sort of error partway through.
4781 : */
4782 722 : exprsDatum = heap_getattr(relation->rd_indextuple,
4783 : Anum_pg_index_indexprs,
4784 : GetPgIndexDescriptor(),
4785 : &isnull);
4786 : Assert(!isnull);
4787 722 : exprsString = TextDatumGetCString(exprsDatum);
4788 722 : result = (List *) stringToNode(exprsString);
4789 722 : pfree(exprsString);
4790 :
4791 : /*
4792 : * Run the expressions through eval_const_expressions. This is not just an
4793 : * optimization, but is necessary, because the planner will be comparing
4794 : * them to similarly-processed qual clauses, and may fail to detect valid
4795 : * matches without this. We must not use canonicalize_qual, however,
4796 : * since these aren't qual expressions.
4797 : */
4798 722 : result = (List *) eval_const_expressions(NULL, (Node *) result);
4799 :
4800 : /* May as well fix opfuncids too */
4801 720 : fix_opfuncids((Node *) result);
4802 :
4803 : /* Now save a copy of the completed tree in the relcache entry. */
4804 720 : oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4805 720 : relation->rd_indexprs = copyObject(result);
4806 720 : MemoryContextSwitchTo(oldcxt);
4807 :
4808 720 : return result;
4809 : }
4810 :
4811 : /*
4812 : * RelationGetDummyIndexExpressions -- get dummy expressions for an index
4813 : *
4814 : * Return a list of dummy expressions (just Const nodes) with the same
4815 : * types/typmods/collations as the index's real expressions. This is
4816 : * useful in situations where we don't want to run any user-defined code.
4817 : */
4818 : List *
4819 140 : RelationGetDummyIndexExpressions(Relation relation)
4820 : {
4821 : List *result;
4822 : Datum exprsDatum;
4823 : bool isnull;
4824 : char *exprsString;
4825 : List *rawExprs;
4826 : ListCell *lc;
4827 :
4828 : /* Quick exit if there is nothing to do. */
4829 280 : if (relation->rd_indextuple == NULL ||
4830 140 : heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4831 128 : return NIL;
4832 :
4833 : /* Extract raw node tree(s) from index tuple. */
4834 12 : exprsDatum = heap_getattr(relation->rd_indextuple,
4835 : Anum_pg_index_indexprs,
4836 : GetPgIndexDescriptor(),
4837 : &isnull);
4838 : Assert(!isnull);
4839 12 : exprsString = TextDatumGetCString(exprsDatum);
4840 12 : rawExprs = (List *) stringToNode(exprsString);
4841 12 : pfree(exprsString);
4842 :
4843 : /* Construct null Consts; the typlen and typbyval are arbitrary. */
4844 12 : result = NIL;
4845 24 : foreach(lc, rawExprs)
4846 : {
4847 12 : Node *rawExpr = (Node *) lfirst(lc);
4848 :
4849 12 : result = lappend(result,
4850 12 : makeConst(exprType(rawExpr),
4851 : exprTypmod(rawExpr),
4852 : exprCollation(rawExpr),
4853 : 1,
4854 : (Datum) 0,
4855 : true,
4856 : true));
4857 : }
4858 :
4859 12 : return result;
4860 : }
4861 :
4862 : /*
4863 : * RelationGetIndexPredicate -- get the index predicate for an index
4864 : *
4865 : * We cache the result of transforming pg_index.indpred into an implicit-AND
4866 : * node tree (suitable for use in planning).
4867 : * If the rel is not an index or has no predicate, we return NIL.
4868 : * Otherwise, the returned tree is copied into the caller's memory context.
4869 : * (We don't want to return a pointer to the relcache copy, since it could
4870 : * disappear due to relcache invalidation.)
4871 : */
4872 : List *
4873 5004230 : RelationGetIndexPredicate(Relation relation)
4874 : {
4875 : List *result;
4876 : Datum predDatum;
4877 : bool isnull;
4878 : char *predString;
4879 : MemoryContext oldcxt;
4880 :
4881 : /* Quick exit if we already computed the result. */
4882 5004230 : if (relation->rd_indpred)
4883 912 : return copyObject(relation->rd_indpred);
4884 :
4885 : /* Quick exit if there is nothing to do. */
4886 10006636 : if (relation->rd_indextuple == NULL ||
4887 5003318 : heap_attisnull(relation->rd_indextuple, Anum_pg_index_indpred, NULL))
4888 5002810 : return NIL;
4889 :
4890 : /*
4891 : * We build the tree we intend to return in the caller's context. After
4892 : * successfully completing the work, we copy it into the relcache entry.
4893 : * This avoids problems if we get some sort of error partway through.
4894 : */
4895 508 : predDatum = heap_getattr(relation->rd_indextuple,
4896 : Anum_pg_index_indpred,
4897 : GetPgIndexDescriptor(),
4898 : &isnull);
4899 : Assert(!isnull);
4900 508 : predString = TextDatumGetCString(predDatum);
4901 508 : result = (List *) stringToNode(predString);
4902 508 : pfree(predString);
4903 :
4904 : /*
4905 : * Run the expression through const-simplification and canonicalization.
4906 : * This is not just an optimization, but is necessary, because the planner
4907 : * will be comparing it to similarly-processed qual clauses, and may fail
4908 : * to detect valid matches without this. This must match the processing
4909 : * done to qual clauses in preprocess_expression()! (We can skip the
4910 : * stuff involving subqueries, however, since we don't allow any in index
4911 : * predicates.)
4912 : */
4913 508 : result = (List *) eval_const_expressions(NULL, (Node *) result);
4914 :
4915 508 : result = (List *) canonicalize_qual((Expr *) result, false);
4916 :
4917 : /* Also convert to implicit-AND format */
4918 508 : result = make_ands_implicit((Expr *) result);
4919 :
4920 : /* May as well fix opfuncids too */
4921 508 : fix_opfuncids((Node *) result);
4922 :
4923 : /* Now save a copy of the completed tree in the relcache entry. */
4924 508 : oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4925 508 : relation->rd_indpred = copyObject(result);
4926 508 : MemoryContextSwitchTo(oldcxt);
4927 :
4928 508 : return result;
4929 : }
4930 :
4931 : /*
4932 : * RelationGetIndexAttrBitmap -- get a bitmap of index attribute numbers
4933 : *
4934 : * The result has a bit set for each attribute used anywhere in the index
4935 : * definitions of all the indexes on this relation. (This includes not only
4936 : * simple index keys, but attributes used in expressions and partial-index
4937 : * predicates.)
4938 : *
4939 : * Depending on attrKind, a bitmap covering the attnums for all index columns,
4940 : * for all potential foreign key columns, or for all columns in the configured
4941 : * replica identity index is returned.
4942 : *
4943 : * Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
4944 : * we can include system attributes (e.g., OID) in the bitmap representation.
4945 : *
4946 : * Caller had better hold at least RowExclusiveLock on the target relation
4947 : * to ensure it is safe (deadlock-free) for us to take locks on the relation's
4948 : * indexes. Note that since the introduction of CREATE INDEX CONCURRENTLY,
4949 : * that lock level doesn't guarantee a stable set of indexes, so we have to
4950 : * be prepared to retry here in case of a change in the set of indexes.
4951 : *
4952 : * The returned result is palloc'd in the caller's memory context and should
4953 : * be bms_free'd when not needed anymore.
4954 : */
4955 : Bitmapset *
4956 1341966 : RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
4957 : {
4958 : Bitmapset *indexattrs; /* indexed columns */
4959 : Bitmapset *uindexattrs; /* columns in unique indexes */
4960 : Bitmapset *pkindexattrs; /* columns in the primary index */
4961 : Bitmapset *idindexattrs; /* columns in the replica identity */
4962 : List *indexoidlist;
4963 : List *newindexoidlist;
4964 : Oid relpkindex;
4965 : Oid relreplindex;
4966 : ListCell *l;
4967 : MemoryContext oldcxt;
4968 :
4969 : /* Quick exit if we already computed the result. */
4970 1341966 : if (relation->rd_indexattr != NULL)
4971 : {
4972 1174006 : switch (attrKind)
4973 : {
4974 368106 : case INDEX_ATTR_BITMAP_ALL:
4975 368106 : return bms_copy(relation->rd_indexattr);
4976 382224 : case INDEX_ATTR_BITMAP_KEY:
4977 382224 : return bms_copy(relation->rd_keyattr);
4978 4 : case INDEX_ATTR_BITMAP_PRIMARY_KEY:
4979 4 : return bms_copy(relation->rd_pkattr);
4980 423672 : case INDEX_ATTR_BITMAP_IDENTITY_KEY:
4981 423672 : return bms_copy(relation->rd_idattr);
4982 0 : default:
4983 167960 : elog(ERROR, "unknown attrKind %u", attrKind);
4984 : }
4985 : }
4986 :
4987 : /* Fast path if definitely no indexes */
4988 167960 : if (!RelationGetForm(relation)->relhasindex)
4989 158726 : return NULL;
4990 :
4991 : /*
4992 : * Get cached list of index OIDs. If we have to start over, we do so here.
4993 : */
4994 9234 : restart:
4995 9234 : indexoidlist = RelationGetIndexList(relation);
4996 :
4997 : /* Fall out if no indexes (but relhasindex was set) */
4998 9234 : if (indexoidlist == NIL)
4999 282 : return NULL;
5000 :
5001 : /*
5002 : * Copy the rd_pkindex and rd_replidindex values computed by
5003 : * RelationGetIndexList before proceeding. This is needed because a
5004 : * relcache flush could occur inside index_open below, resetting the
5005 : * fields managed by RelationGetIndexList. We need to do the work with
5006 : * stable values of these fields.
5007 : */
5008 8952 : relpkindex = relation->rd_pkindex;
5009 8952 : relreplindex = relation->rd_replidindex;
5010 :
5011 : /*
5012 : * For each index, add referenced attributes to indexattrs.
5013 : *
5014 : * Note: we consider all indexes returned by RelationGetIndexList, even if
5015 : * they are not indisready or indisvalid. This is important because an
5016 : * index for which CREATE INDEX CONCURRENTLY has just started must be
5017 : * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
5018 : * CONCURRENTLY is far enough along that we should ignore the index, it
5019 : * won't be returned at all by RelationGetIndexList.
5020 : */
5021 8952 : indexattrs = NULL;
5022 8952 : uindexattrs = NULL;
5023 8952 : pkindexattrs = NULL;
5024 8952 : idindexattrs = NULL;
5025 25456 : foreach(l, indexoidlist)
5026 : {
5027 16504 : Oid indexOid = lfirst_oid(l);
5028 : Relation indexDesc;
5029 : Datum datum;
5030 : bool isnull;
5031 : Node *indexExpressions;
5032 : Node *indexPredicate;
5033 : int i;
5034 : bool isKey; /* candidate key */
5035 : bool isPK; /* primary key */
5036 : bool isIDKey; /* replica identity index */
5037 :
5038 16504 : indexDesc = index_open(indexOid, AccessShareLock);
5039 :
5040 : /*
5041 : * Extract index expressions and index predicate. Note: Don't use
5042 : * RelationGetIndexExpressions()/RelationGetIndexPredicate(), because
5043 : * those might run constant expressions evaluation, which needs a
5044 : * snapshot, which we might not have here. (Also, it's probably more
5045 : * sound to collect the bitmaps before any transformations that might
5046 : * eliminate columns, but the practical impact of this is limited.)
5047 : */
5048 :
5049 16504 : datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indexprs,
5050 : GetPgIndexDescriptor(), &isnull);
5051 16504 : if (!isnull)
5052 20 : indexExpressions = stringToNode(TextDatumGetCString(datum));
5053 : else
5054 16484 : indexExpressions = NULL;
5055 :
5056 16504 : datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indpred,
5057 : GetPgIndexDescriptor(), &isnull);
5058 16504 : if (!isnull)
5059 92 : indexPredicate = stringToNode(TextDatumGetCString(datum));
5060 : else
5061 16412 : indexPredicate = NULL;
5062 :
5063 : /* Can this index be referenced by a foreign key? */
5064 13708 : isKey = indexDesc->rd_index->indisunique &&
5065 30212 : indexExpressions == NULL &&
5066 : indexPredicate == NULL;
5067 :
5068 : /* Is this a primary key? */
5069 16504 : isPK = (indexOid == relpkindex);
5070 :
5071 : /* Is this index the configured (or default) replica identity? */
5072 16504 : isIDKey = (indexOid == relreplindex);
5073 :
5074 : /* Collect simple attribute references */
5075 42146 : for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5076 : {
5077 25642 : int attrnum = indexDesc->rd_index->indkey.values[i];
5078 :
5079 : /*
5080 : * Since we have covering indexes with non-key columns, we must
5081 : * handle them accurately here. non-key columns must be added into
5082 : * indexattrs, since they are in index, and HOT-update shouldn't
5083 : * miss them. Obviously, non-key columns couldn't be referenced by
5084 : * foreign key or identity key. Hence we do not include them into
5085 : * uindexattrs, pkindexattrs and idindexattrs bitmaps.
5086 : */
5087 25642 : if (attrnum != 0)
5088 : {
5089 25622 : indexattrs = bms_add_member(indexattrs,
5090 : attrnum - FirstLowInvalidHeapAttributeNumber);
5091 :
5092 25622 : if (isKey && i < indexDesc->rd_index->indnkeyatts)
5093 20168 : uindexattrs = bms_add_member(uindexattrs,
5094 : attrnum - FirstLowInvalidHeapAttributeNumber);
5095 :
5096 25622 : if (isPK && i < indexDesc->rd_index->indnkeyatts)
5097 2504 : pkindexattrs = bms_add_member(pkindexattrs,
5098 : attrnum - FirstLowInvalidHeapAttributeNumber);
5099 :
5100 25622 : if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
5101 2494 : idindexattrs = bms_add_member(idindexattrs,
5102 : attrnum - FirstLowInvalidHeapAttributeNumber);
5103 : }
5104 : }
5105 :
5106 : /* Collect all attributes used in expressions, too */
5107 16504 : pull_varattnos(indexExpressions, 1, &indexattrs);
5108 :
5109 : /* Collect all attributes in the index predicate, too */
5110 16504 : pull_varattnos(indexPredicate, 1, &indexattrs);
5111 :
5112 16504 : index_close(indexDesc, AccessShareLock);
5113 : }
5114 :
5115 : /*
5116 : * During one of the index_opens in the above loop, we might have received
5117 : * a relcache flush event on this relcache entry, which might have been
5118 : * signaling a change in the rel's index list. If so, we'd better start
5119 : * over to ensure we deliver up-to-date attribute bitmaps.
5120 : */
5121 8952 : newindexoidlist = RelationGetIndexList(relation);
5122 8952 : if (equal(indexoidlist, newindexoidlist) &&
5123 8952 : relpkindex == relation->rd_pkindex &&
5124 8952 : relreplindex == relation->rd_replidindex)
5125 : {
5126 : /* Still the same index set, so proceed */
5127 8952 : list_free(newindexoidlist);
5128 8952 : list_free(indexoidlist);
5129 : }
5130 : else
5131 : {
5132 : /* Gotta do it over ... might as well not leak memory */
5133 0 : list_free(newindexoidlist);
5134 0 : list_free(indexoidlist);
5135 0 : bms_free(uindexattrs);
5136 0 : bms_free(pkindexattrs);
5137 0 : bms_free(idindexattrs);
5138 0 : bms_free(indexattrs);
5139 :
5140 0 : goto restart;
5141 : }
5142 :
5143 : /* Don't leak the old values of these bitmaps, if any */
5144 8952 : bms_free(relation->rd_indexattr);
5145 8952 : relation->rd_indexattr = NULL;
5146 8952 : bms_free(relation->rd_keyattr);
5147 8952 : relation->rd_keyattr = NULL;
5148 8952 : bms_free(relation->rd_pkattr);
5149 8952 : relation->rd_pkattr = NULL;
5150 8952 : bms_free(relation->rd_idattr);
5151 8952 : relation->rd_idattr = NULL;
5152 :
5153 : /*
5154 : * Now save copies of the bitmaps in the relcache entry. We intentionally
5155 : * set rd_indexattr last, because that's the one that signals validity of
5156 : * the values; if we run out of memory before making that copy, we won't
5157 : * leave the relcache entry looking like the other ones are valid but
5158 : * empty.
5159 : */
5160 8952 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
5161 8952 : relation->rd_keyattr = bms_copy(uindexattrs);
5162 8952 : relation->rd_pkattr = bms_copy(pkindexattrs);
5163 8952 : relation->rd_idattr = bms_copy(idindexattrs);
5164 8952 : relation->rd_indexattr = bms_copy(indexattrs);
5165 8952 : MemoryContextSwitchTo(oldcxt);
5166 :
5167 : /* We return our original working copy for caller to play with */
5168 8952 : switch (attrKind)
5169 : {
5170 8072 : case INDEX_ATTR_BITMAP_ALL:
5171 8072 : return indexattrs;
5172 488 : case INDEX_ATTR_BITMAP_KEY:
5173 488 : return uindexattrs;
5174 0 : case INDEX_ATTR_BITMAP_PRIMARY_KEY:
5175 0 : return pkindexattrs;
5176 392 : case INDEX_ATTR_BITMAP_IDENTITY_KEY:
5177 392 : return idindexattrs;
5178 0 : default:
5179 0 : elog(ERROR, "unknown attrKind %u", attrKind);
5180 : return NULL;
5181 : }
5182 : }
5183 :
5184 : /*
5185 : * RelationGetExclusionInfo -- get info about index's exclusion constraint
5186 : *
5187 : * This should be called only for an index that is known to have an
5188 : * associated exclusion constraint. It returns arrays (palloc'd in caller's
5189 : * context) of the exclusion operator OIDs, their underlying functions'
5190 : * OIDs, and their strategy numbers in the index's opclasses. We cache
5191 : * all this information since it requires a fair amount of work to get.
5192 : */
5193 : void
5194 216 : RelationGetExclusionInfo(Relation indexRelation,
5195 : Oid **operators,
5196 : Oid **procs,
5197 : uint16 **strategies)
5198 : {
5199 : int indnkeyatts;
5200 : Oid *ops;
5201 : Oid *funcs;
5202 : uint16 *strats;
5203 : Relation conrel;
5204 : SysScanDesc conscan;
5205 : ScanKeyData skey[1];
5206 : HeapTuple htup;
5207 : bool found;
5208 : MemoryContext oldcxt;
5209 : int i;
5210 :
5211 216 : indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
5212 :
5213 : /* Allocate result space in caller context */
5214 216 : *operators = ops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5215 216 : *procs = funcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5216 216 : *strategies = strats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5217 :
5218 : /* Quick exit if we have the data cached already */
5219 216 : if (indexRelation->rd_exclstrats != NULL)
5220 : {
5221 146 : memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * indnkeyatts);
5222 146 : memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
5223 146 : memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
5224 146 : return;
5225 : }
5226 :
5227 : /*
5228 : * Search pg_constraint for the constraint associated with the index. To
5229 : * make this not too painfully slow, we use the index on conrelid; that
5230 : * will hold the parent relation's OID not the index's own OID.
5231 : *
5232 : * Note: if we wanted to rely on the constraint name matching the index's
5233 : * name, we could just do a direct lookup using pg_constraint's unique
5234 : * index. For the moment it doesn't seem worth requiring that.
5235 : */
5236 70 : ScanKeyInit(&skey[0],
5237 : Anum_pg_constraint_conrelid,
5238 : BTEqualStrategyNumber, F_OIDEQ,
5239 70 : ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5240 :
5241 70 : conrel = table_open(ConstraintRelationId, AccessShareLock);
5242 70 : conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
5243 : NULL, 1, skey);
5244 70 : found = false;
5245 :
5246 332 : while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5247 : {
5248 262 : Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(htup);
5249 : Datum val;
5250 : bool isnull;
5251 : ArrayType *arr;
5252 : int nelem;
5253 :
5254 : /* We want the exclusion constraint owning the index */
5255 262 : if (conform->contype != CONSTRAINT_EXCLUSION ||
5256 150 : conform->conindid != RelationGetRelid(indexRelation))
5257 192 : continue;
5258 :
5259 : /* There should be only one */
5260 70 : if (found)
5261 0 : elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5262 : RelationGetRelationName(indexRelation));
5263 70 : found = true;
5264 :
5265 : /* Extract the operator OIDS from conexclop */
5266 70 : val = fastgetattr(htup,
5267 : Anum_pg_constraint_conexclop,
5268 : conrel->rd_att, &isnull);
5269 70 : if (isnull)
5270 0 : elog(ERROR, "null conexclop for rel %s",
5271 : RelationGetRelationName(indexRelation));
5272 :
5273 70 : arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5274 70 : nelem = ARR_DIMS(arr)[0];
5275 70 : if (ARR_NDIM(arr) != 1 ||
5276 70 : nelem != indnkeyatts ||
5277 70 : ARR_HASNULL(arr) ||
5278 70 : ARR_ELEMTYPE(arr) != OIDOID)
5279 0 : elog(ERROR, "conexclop is not a 1-D Oid array");
5280 :
5281 70 : memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * indnkeyatts);
5282 : }
5283 :
5284 70 : systable_endscan(conscan);
5285 70 : table_close(conrel, AccessShareLock);
5286 :
5287 70 : if (!found)
5288 0 : elog(ERROR, "exclusion constraint record missing for rel %s",
5289 : RelationGetRelationName(indexRelation));
5290 :
5291 : /* We need the func OIDs and strategy numbers too */
5292 154 : for (i = 0; i < indnkeyatts; i++)
5293 : {
5294 84 : funcs[i] = get_opcode(ops[i]);
5295 168 : strats[i] = get_op_opfamily_strategy(ops[i],
5296 84 : indexRelation->rd_opfamily[i]);
5297 : /* shouldn't fail, since it was checked at index creation */
5298 84 : if (strats[i] == InvalidStrategy)
5299 0 : elog(ERROR, "could not find strategy for operator %u in family %u",
5300 : ops[i], indexRelation->rd_opfamily[i]);
5301 : }
5302 :
5303 : /* Save a copy of the results in the relcache entry. */
5304 70 : oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5305 70 : indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5306 70 : indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5307 70 : indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5308 70 : memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
5309 70 : memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
5310 70 : memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
5311 70 : MemoryContextSwitchTo(oldcxt);
5312 : }
5313 :
5314 : /*
5315 : * Get publication actions for the given relation.
5316 : */
5317 : struct PublicationActions *
5318 16420 : GetRelationPublicationActions(Relation relation)
5319 : {
5320 : List *puboids;
5321 : ListCell *lc;
5322 : MemoryContext oldcxt;
5323 16420 : PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5324 :
5325 : /*
5326 : * If not publishable, it publishes no actions. (pgoutput_change() will
5327 : * ignore it.)
5328 : */
5329 16420 : if (!is_publishable_relation(relation))
5330 5910 : return pubactions;
5331 :
5332 10510 : if (relation->rd_pubactions)
5333 8026 : return memcpy(pubactions, relation->rd_pubactions,
5334 : sizeof(PublicationActions));
5335 :
5336 : /* Fetch the publication membership info. */
5337 2484 : puboids = GetRelationPublications(RelationGetRelid(relation));
5338 2484 : if (relation->rd_rel->relispartition)
5339 : {
5340 : /* Add publications that the ancestors are in too. */
5341 664 : List *ancestors = get_partition_ancestors(RelationGetRelid(relation));
5342 : ListCell *lc;
5343 :
5344 1620 : foreach(lc, ancestors)
5345 : {
5346 956 : Oid ancestor = lfirst_oid(lc);
5347 :
5348 956 : puboids = list_concat_unique_oid(puboids,
5349 956 : GetRelationPublications(ancestor));
5350 : }
5351 : }
5352 2484 : puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5353 :
5354 2488 : foreach(lc, puboids)
5355 : {
5356 8 : Oid pubid = lfirst_oid(lc);
5357 : HeapTuple tup;
5358 : Form_pg_publication pubform;
5359 :
5360 8 : tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
5361 :
5362 8 : if (!HeapTupleIsValid(tup))
5363 0 : elog(ERROR, "cache lookup failed for publication %u", pubid);
5364 :
5365 8 : pubform = (Form_pg_publication) GETSTRUCT(tup);
5366 :
5367 8 : pubactions->pubinsert |= pubform->pubinsert;
5368 8 : pubactions->pubupdate |= pubform->pubupdate;
5369 8 : pubactions->pubdelete |= pubform->pubdelete;
5370 8 : pubactions->pubtruncate |= pubform->pubtruncate;
5371 :
5372 8 : ReleaseSysCache(tup);
5373 :
5374 : /*
5375 : * If we know everything is replicated, there is no point to check for
5376 : * other publications.
5377 : */
5378 8 : if (pubactions->pubinsert && pubactions->pubupdate &&
5379 4 : pubactions->pubdelete && pubactions->pubtruncate)
5380 4 : break;
5381 : }
5382 :
5383 2484 : if (relation->rd_pubactions)
5384 : {
5385 0 : pfree(relation->rd_pubactions);
5386 0 : relation->rd_pubactions = NULL;
5387 : }
5388 :
5389 : /* Now save copy of the actions in the relcache entry. */
5390 2484 : oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
5391 2484 : relation->rd_pubactions = palloc(sizeof(PublicationActions));
5392 2484 : memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5393 2484 : MemoryContextSwitchTo(oldcxt);
5394 :
5395 2484 : return pubactions;
5396 : }
5397 :
5398 : /*
5399 : * RelationGetIndexRawAttOptions -- get AM/opclass-specific options for the index
5400 : */
5401 : Datum *
5402 4556242 : RelationGetIndexRawAttOptions(Relation indexrel)
5403 : {
5404 4556242 : Oid indexrelid = RelationGetRelid(indexrel);
5405 4556242 : int16 natts = RelationGetNumberOfAttributes(indexrel);
5406 4556242 : Datum *options = NULL;
5407 : int16 attnum;
5408 :
5409 14589248 : for (attnum = 1; attnum <= natts; attnum++)
5410 : {
5411 10033006 : if (indexrel->rd_indam->amoptsprocnum == 0)
5412 0 : continue;
5413 :
5414 10033006 : if (!OidIsValid(index_getprocid(indexrel, attnum,
5415 : indexrel->rd_indam->amoptsprocnum)))
5416 10033006 : continue;
5417 :
5418 0 : if (!options)
5419 0 : options = palloc0(sizeof(Datum) * natts);
5420 :
5421 0 : options[attnum - 1] = get_attoptions(indexrelid, attnum);
5422 : }
5423 :
5424 4556242 : return options;
5425 : }
5426 :
5427 : static bytea **
5428 776012 : CopyIndexAttOptions(bytea **srcopts, int natts)
5429 : {
5430 776012 : bytea **opts = palloc(sizeof(*opts) * natts);
5431 :
5432 2155354 : for (int i = 0; i < natts; i++)
5433 : {
5434 1379342 : bytea *opt = srcopts[i];
5435 :
5436 1380232 : opts[i] = !opt ? NULL : (bytea *)
5437 890 : DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
5438 : }
5439 :
5440 776012 : return opts;
5441 : }
5442 :
5443 : /*
5444 : * RelationGetIndexAttOptions
5445 : * get AM/opclass-specific options for an index parsed into a binary form
5446 : */
5447 : bytea **
5448 1396526 : RelationGetIndexAttOptions(Relation relation, bool copy)
5449 : {
5450 : MemoryContext oldcxt;
5451 1396526 : bytea **opts = relation->rd_opcoptions;
5452 1396526 : Oid relid = RelationGetRelid(relation);
5453 1396526 : int natts = RelationGetNumberOfAttributes(relation); /* XXX
5454 : * IndexRelationGetNumberOfKeyAttributes */
5455 : int i;
5456 :
5457 : /* Try to copy cached options. */
5458 1396526 : if (opts)
5459 1047022 : return copy ? CopyIndexAttOptions(opts, natts) : opts;
5460 :
5461 : /* Get and parse opclass options. */
5462 349504 : opts = palloc0(sizeof(*opts) * natts);
5463 :
5464 950500 : for (i = 0; i < natts; i++)
5465 : {
5466 601000 : if (criticalRelcachesBuilt && relid != AttributeRelidNumIndexId)
5467 : {
5468 475236 : Datum attoptions = get_attoptions(relid, i + 1);
5469 :
5470 475236 : opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
5471 :
5472 475232 : if (attoptions != (Datum) 0)
5473 84 : pfree(DatumGetPointer(attoptions));
5474 : }
5475 : }
5476 :
5477 : /* Copy parsed options to the cache. */
5478 349500 : oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
5479 349500 : relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
5480 349500 : MemoryContextSwitchTo(oldcxt);
5481 :
5482 349500 : if (copy)
5483 0 : return opts;
5484 :
5485 950496 : for (i = 0; i < natts; i++)
5486 : {
5487 600996 : if (opts[i])
5488 136 : pfree(opts[i]);
5489 : }
5490 :
5491 349500 : pfree(opts);
5492 :
5493 349500 : return relation->rd_opcoptions;
5494 : }
5495 :
5496 : /*
5497 : * Routines to support ereport() reports of relation-related errors
5498 : *
5499 : * These could have been put into elog.c, but it seems like a module layering
5500 : * violation to have elog.c calling relcache or syscache stuff --- and we
5501 : * definitely don't want elog.h including rel.h. So we put them here.
5502 : */
5503 :
5504 : /*
5505 : * errtable --- stores schema_name and table_name of a table
5506 : * within the current errordata.
5507 : */
5508 : int
5509 1846 : errtable(Relation rel)
5510 : {
5511 1846 : err_generic_string(PG_DIAG_SCHEMA_NAME,
5512 1846 : get_namespace_name(RelationGetNamespace(rel)));
5513 1846 : err_generic_string(PG_DIAG_TABLE_NAME, RelationGetRelationName(rel));
5514 :
5515 1846 : return 0; /* return value does not matter */
5516 : }
5517 :
5518 : /*
5519 : * errtablecol --- stores schema_name, table_name and column_name
5520 : * of a table column within the current errordata.
5521 : *
5522 : * The column is specified by attribute number --- for most callers, this is
5523 : * easier and less error-prone than getting the column name for themselves.
5524 : */
5525 : int
5526 222 : errtablecol(Relation rel, int attnum)
5527 : {
5528 222 : TupleDesc reldesc = RelationGetDescr(rel);
5529 : const char *colname;
5530 :
5531 : /* Use reldesc if it's a user attribute, else consult the catalogs */
5532 222 : if (attnum > 0 && attnum <= reldesc->natts)
5533 222 : colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5534 : else
5535 0 : colname = get_attname(RelationGetRelid(rel), attnum, false);
5536 :
5537 222 : return errtablecolname(rel, colname);
5538 : }
5539 :
5540 : /*
5541 : * errtablecolname --- stores schema_name, table_name and column_name
5542 : * of a table column within the current errordata, where the column name is
5543 : * given directly rather than extracted from the relation's catalog data.
5544 : *
5545 : * Don't use this directly unless errtablecol() is inconvenient for some
5546 : * reason. This might possibly be needed during intermediate states in ALTER
5547 : * TABLE, for instance.
5548 : */
5549 : int
5550 222 : errtablecolname(Relation rel, const char *colname)
5551 : {
5552 222 : errtable(rel);
5553 222 : err_generic_string(PG_DIAG_COLUMN_NAME, colname);
5554 :
5555 222 : return 0; /* return value does not matter */
5556 : }
5557 :
5558 : /*
5559 : * errtableconstraint --- stores schema_name, table_name and constraint_name
5560 : * of a table-related constraint within the current errordata.
5561 : */
5562 : int
5563 1310 : errtableconstraint(Relation rel, const char *conname)
5564 : {
5565 1310 : errtable(rel);
5566 1310 : err_generic_string(PG_DIAG_CONSTRAINT_NAME, conname);
5567 :
5568 1310 : return 0; /* return value does not matter */
5569 : }
5570 :
5571 :
5572 : /*
5573 : * load_relcache_init_file, write_relcache_init_file
5574 : *
5575 : * In late 1992, we started regularly having databases with more than
5576 : * a thousand classes in them. With this number of classes, it became
5577 : * critical to do indexed lookups on the system catalogs.
5578 : *
5579 : * Bootstrapping these lookups is very hard. We want to be able to
5580 : * use an index on pg_attribute, for example, but in order to do so,
5581 : * we must have read pg_attribute for the attributes in the index,
5582 : * which implies that we need to use the index.
5583 : *
5584 : * In order to get around the problem, we do the following:
5585 : *
5586 : * + When the database system is initialized (at initdb time), we
5587 : * don't use indexes. We do sequential scans.
5588 : *
5589 : * + When the backend is started up in normal mode, we load an image
5590 : * of the appropriate relation descriptors, in internal format,
5591 : * from an initialization file in the data/base/... directory.
5592 : *
5593 : * + If the initialization file isn't there, then we create the
5594 : * relation descriptors using sequential scans and write 'em to
5595 : * the initialization file for use by subsequent backends.
5596 : *
5597 : * As of Postgres 9.0, there is one local initialization file in each
5598 : * database, plus one shared initialization file for shared catalogs.
5599 : *
5600 : * We could dispense with the initialization files and just build the
5601 : * critical reldescs the hard way on every backend startup, but that
5602 : * slows down backend startup noticeably.
5603 : *
5604 : * We can in fact go further, and save more relcache entries than
5605 : * just the ones that are absolutely critical; this allows us to speed
5606 : * up backend startup by not having to build such entries the hard way.
5607 : * Presently, all the catalog and index entries that are referred to
5608 : * by catcaches are stored in the initialization files.
5609 : *
5610 : * The same mechanism that detects when catcache and relcache entries
5611 : * need to be invalidated (due to catalog updates) also arranges to
5612 : * unlink the initialization files when the contents may be out of date.
5613 : * The files will then be rebuilt during the next backend startup.
5614 : */
5615 :
5616 : /*
5617 : * load_relcache_init_file -- attempt to load cache from the shared
5618 : * or local cache init file
5619 : *
5620 : * If successful, return true and set criticalRelcachesBuilt or
5621 : * criticalSharedRelcachesBuilt to true.
5622 : * If not successful, return false.
5623 : *
5624 : * NOTE: we assume we are already switched into CacheMemoryContext.
5625 : */
5626 : static bool
5627 22842 : load_relcache_init_file(bool shared)
5628 : {
5629 : FILE *fp;
5630 : char initfilename[MAXPGPATH];
5631 : Relation *rels;
5632 : int relno,
5633 : num_rels,
5634 : max_rels,
5635 : nailed_rels,
5636 : nailed_indexes,
5637 : magic;
5638 : int i;
5639 :
5640 22842 : if (shared)
5641 12078 : snprintf(initfilename, sizeof(initfilename), "global/%s",
5642 : RELCACHE_INIT_FILENAME);
5643 : else
5644 10764 : snprintf(initfilename, sizeof(initfilename), "%s/%s",
5645 : DatabasePath, RELCACHE_INIT_FILENAME);
5646 :
5647 22842 : fp = AllocateFile(initfilename, PG_BINARY_R);
5648 22842 : if (fp == NULL)
5649 3742 : return false;
5650 :
5651 : /*
5652 : * Read the index relcache entries from the file. Note we will not enter
5653 : * any of them into the cache if the read fails partway through; this
5654 : * helps to guard against broken init files.
5655 : */
5656 19100 : max_rels = 100;
5657 19100 : rels = (Relation *) palloc(max_rels * sizeof(Relation));
5658 19100 : num_rels = 0;
5659 19100 : nailed_rels = nailed_indexes = 0;
5660 :
5661 : /* check for correct magic number (compatible version) */
5662 19100 : if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
5663 0 : goto read_failed;
5664 19100 : if (magic != RELCACHE_INIT_FILEMAGIC)
5665 0 : goto read_failed;
5666 :
5667 19100 : for (relno = 0;; relno++)
5668 1193780 : {
5669 : Size len;
5670 : size_t nread;
5671 : Relation rel;
5672 : Form_pg_class relform;
5673 : bool has_not_null;
5674 :
5675 : /* first read the relation descriptor length */
5676 1212880 : nread = fread(&len, 1, sizeof(len), fp);
5677 1212880 : if (nread != sizeof(len))
5678 : {
5679 19100 : if (nread == 0)
5680 19100 : break; /* end of file */
5681 0 : goto read_failed;
5682 : }
5683 :
5684 : /* safety check for incompatible relcache layout */
5685 1193780 : if (len != sizeof(RelationData))
5686 0 : goto read_failed;
5687 :
5688 : /* allocate another relcache header */
5689 1193780 : if (num_rels >= max_rels)
5690 : {
5691 9232 : max_rels *= 2;
5692 9232 : rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
5693 : }
5694 :
5695 1193780 : rel = rels[num_rels++] = (Relation) palloc(len);
5696 :
5697 : /* then, read the Relation structure */
5698 1193780 : if (fread(rel, 1, len, fp) != len)
5699 0 : goto read_failed;
5700 :
5701 : /* next read the relation tuple form */
5702 1193780 : if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5703 0 : goto read_failed;
5704 :
5705 1193780 : relform = (Form_pg_class) palloc(len);
5706 1193780 : if (fread(relform, 1, len, fp) != len)
5707 0 : goto read_failed;
5708 :
5709 1193780 : rel->rd_rel = relform;
5710 :
5711 : /* initialize attribute tuple forms */
5712 1193780 : rel->rd_att = CreateTemplateTupleDesc(relform->relnatts);
5713 1193780 : rel->rd_att->tdrefcount = 1; /* mark as refcounted */
5714 :
5715 1193780 : rel->rd_att->tdtypeid = relform->reltype ? relform->reltype : RECORDOID;
5716 1193780 : rel->rd_att->tdtypmod = -1; /* just to be sure */
5717 :
5718 : /* next read all the attribute tuple form data entries */
5719 1193780 : has_not_null = false;
5720 6906112 : for (i = 0; i < relform->relnatts; i++)
5721 : {
5722 5712332 : Form_pg_attribute attr = TupleDescAttr(rel->rd_att, i);
5723 :
5724 5712332 : if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5725 0 : goto read_failed;
5726 5712332 : if (len != ATTRIBUTE_FIXED_PART_SIZE)
5727 0 : goto read_failed;
5728 5712332 : if (fread(attr, 1, len, fp) != len)
5729 0 : goto read_failed;
5730 :
5731 5712332 : has_not_null |= attr->attnotnull;
5732 : }
5733 :
5734 : /* next read the access method specific field */
5735 1193780 : if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5736 0 : goto read_failed;
5737 1193780 : if (len > 0)
5738 : {
5739 0 : rel->rd_options = palloc(len);
5740 0 : if (fread(rel->rd_options, 1, len, fp) != len)
5741 0 : goto read_failed;
5742 0 : if (len != VARSIZE(rel->rd_options))
5743 0 : goto read_failed; /* sanity check */
5744 : }
5745 : else
5746 : {
5747 1193780 : rel->rd_options = NULL;
5748 : }
5749 :
5750 : /* mark not-null status */
5751 1193780 : if (has_not_null)
5752 : {
5753 447588 : TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
5754 :
5755 447588 : constr->has_not_null = true;
5756 447588 : rel->rd_att->constr = constr;
5757 : }
5758 :
5759 : /*
5760 : * If it's an index, there's more to do. Note we explicitly ignore
5761 : * partitioned indexes here.
5762 : */
5763 1193780 : if (rel->rd_rel->relkind == RELKIND_INDEX)
5764 : {
5765 : MemoryContext indexcxt;
5766 : Oid *opfamily;
5767 : Oid *opcintype;
5768 : RegProcedure *support;
5769 : int nsupport;
5770 : int16 *indoption;
5771 : Oid *indcollation;
5772 :
5773 : /* Count nailed indexes to ensure we have 'em all */
5774 746192 : if (rel->rd_isnailed)
5775 123832 : nailed_indexes++;
5776 :
5777 : /* next, read the pg_index tuple */
5778 746192 : if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5779 0 : goto read_failed;
5780 :
5781 746192 : rel->rd_indextuple = (HeapTuple) palloc(len);
5782 746192 : if (fread(rel->rd_indextuple, 1, len, fp) != len)
5783 0 : goto read_failed;
5784 :
5785 : /* Fix up internal pointers in the tuple -- see heap_copytuple */
5786 746192 : rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
5787 746192 : rel->rd_index = (Form_pg_index) GETSTRUCT(rel->rd_indextuple);
5788 :
5789 : /*
5790 : * prepare index info context --- parameters should match
5791 : * RelationInitIndexAccessInfo
5792 : */
5793 746192 : indexcxt = AllocSetContextCreate(CacheMemoryContext,
5794 : "index info",
5795 : ALLOCSET_SMALL_SIZES);
5796 746192 : rel->rd_indexcxt = indexcxt;
5797 746192 : MemoryContextCopyAndSetIdentifier(indexcxt,
5798 : RelationGetRelationName(rel));
5799 :
5800 : /*
5801 : * Now we can fetch the index AM's API struct. (We can't store
5802 : * that in the init file, since it contains function pointers that
5803 : * might vary across server executions. Fortunately, it should be
5804 : * safe to call the amhandler even while bootstrapping indexes.)
5805 : */
5806 746192 : InitIndexAmRoutine(rel);
5807 :
5808 : /* next, read the vector of opfamily OIDs */
5809 746192 : if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5810 0 : goto read_failed;
5811 :
5812 746192 : opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
5813 746192 : if (fread(opfamily, 1, len, fp) != len)
5814 0 : goto read_failed;
5815 :
5816 746192 : rel->rd_opfamily = opfamily;
5817 :
5818 : /* next, read the vector of opcintype OIDs */
5819 746192 : if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5820 0 : goto read_failed;
5821 :
5822 746192 : opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
5823 746192 : if (fread(opcintype, 1, len, fp) != len)
5824 0 : goto read_failed;
5825 :
5826 746192 : rel->rd_opcintype = opcintype;
5827 :
5828 : /* next, read the vector of support procedure OIDs */
5829 746192 : if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5830 0 : goto read_failed;
5831 746192 : support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
5832 746192 : if (fread(support, 1, len, fp) != len)
5833 0 : goto read_failed;
5834 :
5835 746192 : rel->rd_support = support;
5836 :
5837 : /* next, read the vector of collation OIDs */
5838 746192 : if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5839 0 : goto read_failed;
5840 :
5841 746192 : indcollation = (Oid *) MemoryContextAlloc(indexcxt, len);
5842 746192 : if (fread(indcollation, 1, len, fp) != len)
5843 0 : goto read_failed;
5844 :
5845 746192 : rel->rd_indcollation = indcollation;
5846 :
5847 : /* finally, read the vector of indoption values */
5848 746192 : if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5849 0 : goto read_failed;
5850 :
5851 746192 : indoption = (int16 *) MemoryContextAlloc(indexcxt, len);
5852 746192 : if (fread(indoption, 1, len, fp) != len)
5853 0 : goto read_failed;
5854 :
5855 746192 : rel->rd_indoption = indoption;
5856 :
5857 : /* finally, read the vector of opcoptions values */
5858 746192 : rel->rd_opcoptions = (bytea **)
5859 746192 : MemoryContextAllocZero(indexcxt, sizeof(*rel->rd_opcoptions) * relform->relnatts);
5860 :
5861 1966396 : for (i = 0; i < relform->relnatts; i++)
5862 : {
5863 1220204 : if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5864 0 : goto read_failed;
5865 :
5866 1220204 : if (len > 0)
5867 : {
5868 0 : rel->rd_opcoptions[i] = (bytea *) MemoryContextAlloc(indexcxt, len);
5869 0 : if (fread(rel->rd_opcoptions[i], 1, len, fp) != len)
5870 0 : goto read_failed;
5871 : }
5872 : }
5873 :
5874 : /* set up zeroed fmgr-info vector */
5875 746192 : nsupport = relform->relnatts * rel->rd_indam->amsupport;
5876 746192 : rel->rd_supportinfo = (FmgrInfo *)
5877 746192 : MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
5878 : }
5879 : else
5880 : {
5881 : /* Count nailed rels to ensure we have 'em all */
5882 447588 : if (rel->rd_isnailed)
5883 86268 : nailed_rels++;
5884 :
5885 : /* Load table AM data */
5886 447588 : if (rel->rd_rel->relkind == RELKIND_RELATION ||
5887 0 : rel->rd_rel->relkind == RELKIND_SEQUENCE ||
5888 0 : rel->rd_rel->relkind == RELKIND_TOASTVALUE ||
5889 0 : rel->rd_rel->relkind == RELKIND_MATVIEW)
5890 447588 : RelationInitTableAccessMethod(rel);
5891 :
5892 : Assert(rel->rd_index == NULL);
5893 : Assert(rel->rd_indextuple == NULL);
5894 : Assert(rel->rd_indexcxt == NULL);
5895 : Assert(rel->rd_indam == NULL);
5896 : Assert(rel->rd_opfamily == NULL);
5897 : Assert(rel->rd_opcintype == NULL);
5898 : Assert(rel->rd_support == NULL);
5899 : Assert(rel->rd_supportinfo == NULL);
5900 : Assert(rel->rd_indoption == NULL);
5901 : Assert(rel->rd_indcollation == NULL);
5902 : Assert(rel->rd_opcoptions == NULL);
5903 : }
5904 :
5905 : /*
5906 : * Rules and triggers are not saved (mainly because the internal
5907 : * format is complex and subject to change). They must be rebuilt if
5908 : * needed by RelationCacheInitializePhase3. This is not expected to
5909 : * be a big performance hit since few system catalogs have such. Ditto
5910 : * for RLS policy data, partition info, index expressions, predicates,
5911 : * exclusion info, and FDW info.
5912 : */
5913 1193780 : rel->rd_rules = NULL;
5914 1193780 : rel->rd_rulescxt = NULL;
5915 1193780 : rel->trigdesc = NULL;
5916 1193780 : rel->rd_rsdesc = NULL;
5917 1193780 : rel->rd_partkey = NULL;
5918 1193780 : rel->rd_partkeycxt = NULL;
5919 1193780 : rel->rd_partdesc = NULL;
5920 1193780 : rel->rd_pdcxt = NULL;
5921 1193780 : rel->rd_partcheck = NIL;
5922 1193780 : rel->rd_partcheckvalid = false;
5923 1193780 : rel->rd_partcheckcxt = NULL;
5924 1193780 : rel->rd_indexprs = NIL;
5925 1193780 : rel->rd_indpred = NIL;
5926 1193780 : rel->rd_exclops = NULL;
5927 1193780 : rel->rd_exclprocs = NULL;
5928 1193780 : rel->rd_exclstrats = NULL;
5929 1193780 : rel->rd_fdwroutine = NULL;
5930 :
5931 : /*
5932 : * Reset transient-state fields in the relcache entry
5933 : */
5934 1193780 : rel->rd_smgr = NULL;
5935 1193780 : if (rel->rd_isnailed)
5936 210100 : rel->rd_refcnt = 1;
5937 : else
5938 983680 : rel->rd_refcnt = 0;
5939 1193780 : rel->rd_indexvalid = false;
5940 1193780 : rel->rd_indexlist = NIL;
5941 1193780 : rel->rd_pkindex = InvalidOid;
5942 1193780 : rel->rd_replidindex = InvalidOid;
5943 1193780 : rel->rd_indexattr = NULL;
5944 1193780 : rel->rd_keyattr = NULL;
5945 1193780 : rel->rd_pkattr = NULL;
5946 1193780 : rel->rd_idattr = NULL;
5947 1193780 : rel->rd_pubactions = NULL;
5948 1193780 : rel->rd_statvalid = false;
5949 1193780 : rel->rd_version_checked = false;
5950 1193780 : rel->rd_statlist = NIL;
5951 1193780 : rel->rd_fkeyvalid = false;
5952 1193780 : rel->rd_fkeylist = NIL;
5953 1193780 : rel->rd_createSubid = InvalidSubTransactionId;
5954 1193780 : rel->rd_newRelfilenodeSubid = InvalidSubTransactionId;
5955 1193780 : rel->rd_firstRelfilenodeSubid = InvalidSubTransactionId;
5956 1193780 : rel->rd_droppedSubid = InvalidSubTransactionId;
5957 1193780 : rel->rd_amcache = NULL;
5958 2387560 : MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info));
5959 :
5960 : /*
5961 : * Recompute lock and physical addressing info. This is needed in
5962 : * case the pg_internal.init file was copied from some other database
5963 : * by CREATE DATABASE.
5964 : */
5965 1193780 : RelationInitLockInfo(rel);
5966 1193780 : RelationInitPhysicalAddr(rel);
5967 : }
5968 :
5969 : /*
5970 : * We reached the end of the init file without apparent problem. Did we
5971 : * get the right number of nailed items? This is a useful crosscheck in
5972 : * case the set of critical rels or indexes changes. However, that should
5973 : * not happen in a normally-running system, so let's bleat if it does.
5974 : *
5975 : * For the shared init file, we're called before client authentication is
5976 : * done, which means that elog(WARNING) will go only to the postmaster
5977 : * log, where it's easily missed. To ensure that developers notice bad
5978 : * values of NUM_CRITICAL_SHARED_RELS/NUM_CRITICAL_SHARED_INDEXES, we put
5979 : * an Assert(false) there.
5980 : */
5981 19100 : if (shared)
5982 : {
5983 9868 : if (nailed_rels != NUM_CRITICAL_SHARED_RELS ||
5984 : nailed_indexes != NUM_CRITICAL_SHARED_INDEXES)
5985 : {
5986 0 : elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
5987 : nailed_rels, nailed_indexes,
5988 : NUM_CRITICAL_SHARED_RELS, NUM_CRITICAL_SHARED_INDEXES);
5989 : /* Make sure we get developers' attention about this */
5990 : Assert(false);
5991 : /* In production builds, recover by bootstrapping the relcache */
5992 0 : goto read_failed;
5993 : }
5994 : }
5995 : else
5996 : {
5997 9232 : if (nailed_rels != NUM_CRITICAL_LOCAL_RELS ||
5998 : nailed_indexes != NUM_CRITICAL_LOCAL_INDEXES)
5999 : {
6000 0 : elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
6001 : nailed_rels, nailed_indexes,
6002 : NUM_CRITICAL_LOCAL_RELS, NUM_CRITICAL_LOCAL_INDEXES);
6003 : /* We don't need an Assert() in this case */
6004 0 : goto read_failed;
6005 : }
6006 : }
6007 :
6008 : /*
6009 : * OK, all appears well.
6010 : *
6011 : * Now insert all the new relcache entries into the cache.
6012 : */
6013 1212880 : for (relno = 0; relno < num_rels; relno++)
6014 : {
6015 1193780 : RelationCacheInsert(rels[relno], false);
6016 : }
6017 :
6018 19100 : pfree(rels);
6019 19100 : FreeFile(fp);
6020 :
6021 19100 : if (shared)
6022 9868 : criticalSharedRelcachesBuilt = true;
6023 : else
6024 9232 : criticalRelcachesBuilt = true;
6025 19100 : return true;
6026 :
6027 : /*
6028 : * init file is broken, so do it the hard way. We don't bother trying to
6029 : * free the clutter we just allocated; it's not in the relcache so it
6030 : * won't hurt.
6031 : */
6032 0 : read_failed:
6033 0 : pfree(rels);
6034 0 : FreeFile(fp);
6035 :
6036 0 : return false;
6037 : }
6038 :
6039 : /*
6040 : * Write out a new initialization file with the current contents
6041 : * of the relcache (either shared rels or local rels, as indicated).
6042 : */
6043 : static void
6044 3096 : write_relcache_init_file(bool shared)
6045 : {
6046 : FILE *fp;
6047 : char tempfilename[MAXPGPATH];
6048 : char finalfilename[MAXPGPATH];
6049 : int magic;
6050 : HASH_SEQ_STATUS status;
6051 : RelIdCacheEnt *idhentry;
6052 : int i;
6053 :
6054 : /*
6055 : * If we have already received any relcache inval events, there's no
6056 : * chance of succeeding so we may as well skip the whole thing.
6057 : */
6058 3096 : if (relcacheInvalsReceived != 0L)
6059 12 : return;
6060 :
6061 : /*
6062 : * We must write a temporary file and rename it into place. Otherwise,
6063 : * another backend starting at about the same time might crash trying to
6064 : * read the partially-complete file.
6065 : */
6066 3084 : if (shared)
6067 : {
6068 1542 : snprintf(tempfilename, sizeof(tempfilename), "global/%s.%d",
6069 : RELCACHE_INIT_FILENAME, MyProcPid);
6070 1542 : snprintf(finalfilename, sizeof(finalfilename), "global/%s",
6071 : RELCACHE_INIT_FILENAME);
6072 : }
6073 : else
6074 : {
6075 1542 : snprintf(tempfilename, sizeof(tempfilename), "%s/%s.%d",
6076 : DatabasePath, RELCACHE_INIT_FILENAME, MyProcPid);
6077 1542 : snprintf(finalfilename, sizeof(finalfilename), "%s/%s",
6078 : DatabasePath, RELCACHE_INIT_FILENAME);
6079 : }
6080 :
6081 3084 : unlink(tempfilename); /* in case it exists w/wrong permissions */
6082 :
6083 3084 : fp = AllocateFile(tempfilename, PG_BINARY_W);
6084 3084 : if (fp == NULL)
6085 : {
6086 : /*
6087 : * We used to consider this a fatal error, but we might as well
6088 : * continue with backend startup ...
6089 : */
6090 0 : ereport(WARNING,
6091 : (errcode_for_file_access(),
6092 : errmsg("could not create relation-cache initialization file \"%s\": %m",
6093 : tempfilename),
6094 : errdetail("Continuing anyway, but there's something wrong.")));
6095 0 : return;
6096 : }
6097 :
6098 : /*
6099 : * Write a magic number to serve as a file version identifier. We can
6100 : * change the magic number whenever the relcache layout changes.
6101 : */
6102 3084 : magic = RELCACHE_INIT_FILEMAGIC;
6103 3084 : if (fwrite(&magic, 1, sizeof(magic), fp) != sizeof(magic))
6104 0 : elog(FATAL, "could not write init file");
6105 :
6106 : /*
6107 : * Write all the appropriate reldescs (in no particular order).
6108 : */
6109 3084 : hash_seq_init(&status, RelationIdCache);
6110 :
6111 397836 : while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
6112 : {
6113 394752 : Relation rel = idhentry->reldesc;
6114 394752 : Form_pg_class relform = rel->rd_rel;
6115 :
6116 : /* ignore if not correct group */
6117 394752 : if (relform->relisshared != shared)
6118 197376 : continue;
6119 :
6120 : /*
6121 : * Ignore if not supposed to be in init file. We can allow any shared
6122 : * relation that's been loaded so far to be in the shared init file,
6123 : * but unshared relations must be ones that should be in the local
6124 : * file per RelationIdIsInInitFile. (Note: if you want to change the
6125 : * criterion for rels to be kept in the init file, see also inval.c.
6126 : * The reason for filtering here is to be sure that we don't put
6127 : * anything into the local init file for which a relcache inval would
6128 : * not cause invalidation of that init file.)
6129 : */
6130 197376 : if (!shared && !RelationIdIsInInitFile(RelationGetRelid(rel)))
6131 : {
6132 : /* Nailed rels had better get stored. */
6133 : Assert(!rel->rd_isnailed);
6134 0 : continue;
6135 : }
6136 :
6137 : /* first write the relcache entry proper */
6138 197376 : write_item(rel, sizeof(RelationData), fp);
6139 :
6140 : /* next write the relation tuple form */
6141 197376 : write_item(relform, CLASS_TUPLE_SIZE, fp);
6142 :
6143 : /* next, do all the attribute tuple form data entries */
6144 1144164 : for (i = 0; i < relform->relnatts; i++)
6145 : {
6146 946788 : write_item(TupleDescAttr(rel->rd_att, i),
6147 : ATTRIBUTE_FIXED_PART_SIZE, fp);
6148 : }
6149 :
6150 : /* next, do the access method specific field */
6151 197376 : write_item(rel->rd_options,
6152 197376 : (rel->rd_options ? VARSIZE(rel->rd_options) : 0),
6153 : fp);
6154 :
6155 : /*
6156 : * If it's an index, there's more to do. Note we explicitly ignore
6157 : * partitioned indexes here.
6158 : */
6159 197376 : if (rel->rd_rel->relkind == RELKIND_INDEX)
6160 : {
6161 : /* write the pg_index tuple */
6162 : /* we assume this was created by heap_copytuple! */
6163 123360 : write_item(rel->rd_indextuple,
6164 123360 : HEAPTUPLESIZE + rel->rd_indextuple->t_len,
6165 : fp);
6166 :
6167 : /* next, write the vector of opfamily OIDs */
6168 123360 : write_item(rel->rd_opfamily,
6169 123360 : relform->relnatts * sizeof(Oid),
6170 : fp);
6171 :
6172 : /* next, write the vector of opcintype OIDs */
6173 123360 : write_item(rel->rd_opcintype,
6174 123360 : relform->relnatts * sizeof(Oid),
6175 : fp);
6176 :
6177 : /* next, write the vector of support procedure OIDs */
6178 123360 : write_item(rel->rd_support,
6179 123360 : relform->relnatts * (rel->rd_indam->amsupport * sizeof(RegProcedure)),
6180 : fp);
6181 :
6182 : /* next, write the vector of collation OIDs */
6183 123360 : write_item(rel->rd_indcollation,
6184 123360 : relform->relnatts * sizeof(Oid),
6185 : fp);
6186 :
6187 : /* finally, write the vector of indoption values */
6188 123360 : write_item(rel->rd_indoption,
6189 123360 : relform->relnatts * sizeof(int16),
6190 : fp);
6191 :
6192 : Assert(rel->rd_opcoptions);
6193 :
6194 : /* finally, write the vector of opcoptions values */
6195 325362 : for (i = 0; i < relform->relnatts; i++)
6196 : {
6197 202002 : bytea *opt = rel->rd_opcoptions[i];
6198 :
6199 202002 : write_item(opt, opt ? VARSIZE(opt) : 0, fp);
6200 : }
6201 : }
6202 : }
6203 :
6204 3084 : if (FreeFile(fp))
6205 0 : elog(FATAL, "could not write init file");
6206 :
6207 : /*
6208 : * Now we have to check whether the data we've so painstakingly
6209 : * accumulated is already obsolete due to someone else's just-committed
6210 : * catalog changes. If so, we just delete the temp file and leave it to
6211 : * the next backend to try again. (Our own relcache entries will be
6212 : * updated by SI message processing, but we can't be sure whether what we
6213 : * wrote out was up-to-date.)
6214 : *
6215 : * This mustn't run concurrently with the code that unlinks an init file
6216 : * and sends SI messages, so grab a serialization lock for the duration.
6217 : */
6218 3084 : LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6219 :
6220 : /* Make sure we have seen all incoming SI messages */
6221 3084 : AcceptInvalidationMessages();
6222 :
6223 : /*
6224 : * If we have received any SI relcache invals since backend start, assume
6225 : * we may have written out-of-date data.
6226 : */
6227 3084 : if (relcacheInvalsReceived == 0L)
6228 : {
6229 : /*
6230 : * OK, rename the temp file to its final name, deleting any
6231 : * previously-existing init file.
6232 : *
6233 : * Note: a failure here is possible under Cygwin, if some other
6234 : * backend is holding open an unlinked-but-not-yet-gone init file. So
6235 : * treat this as a noncritical failure; just remove the useless temp
6236 : * file on failure.
6237 : */
6238 3084 : if (rename(tempfilename, finalfilename) < 0)
6239 0 : unlink(tempfilename);
6240 : }
6241 : else
6242 : {
6243 : /* Delete the already-obsolete temp file */
6244 0 : unlink(tempfilename);
6245 : }
6246 :
6247 3084 : LWLockRelease(RelCacheInitLock);
6248 : }
6249 :
6250 : /* write a chunk of data preceded by its length */
6251 : static void
6252 2481078 : write_item(const void *data, Size len, FILE *fp)
6253 : {
6254 2481078 : if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
6255 0 : elog(FATAL, "could not write init file");
6256 2481078 : if (fwrite(data, 1, len, fp) != len)
6257 0 : elog(FATAL, "could not write init file");
6258 2481078 : }
6259 :
6260 : /*
6261 : * Determine whether a given relation (identified by OID) is one of the ones
6262 : * we should store in a relcache init file.
6263 : *
6264 : * We must cache all nailed rels, and for efficiency we should cache every rel
6265 : * that supports a syscache. The former set is almost but not quite a subset
6266 : * of the latter. The special cases are relations where
6267 : * RelationCacheInitializePhase2/3 chooses to nail for efficiency reasons, but
6268 : * which do not support any syscache.
6269 : */
6270 : bool
6271 1889816 : RelationIdIsInInitFile(Oid relationId)
6272 : {
6273 1889816 : if (relationId == SharedSecLabelRelationId ||
6274 1886530 : relationId == TriggerRelidNameIndexId ||
6275 1886024 : relationId == DatabaseNameIndexId ||
6276 : relationId == SharedSecLabelObjectIndexId)
6277 : {
6278 : /*
6279 : * If this Assert fails, we don't need the applicable special case
6280 : * anymore.
6281 : */
6282 : Assert(!RelationSupportsSysCache(relationId));
6283 3856 : return true;
6284 : }
6285 1885960 : return RelationSupportsSysCache(relationId);
6286 : }
6287 :
6288 : /*
6289 : * Invalidate (remove) the init file during commit of a transaction that
6290 : * changed one or more of the relation cache entries that are kept in the
6291 : * local init file.
6292 : *
6293 : * To be safe against concurrent inspection or rewriting of the init file,
6294 : * we must take RelCacheInitLock, then remove the old init file, then send
6295 : * the SI messages that include relcache inval for such relations, and then
6296 : * release RelCacheInitLock. This serializes the whole affair against
6297 : * write_relcache_init_file, so that we can be sure that any other process
6298 : * that's concurrently trying to create a new init file won't move an
6299 : * already-stale version into place after we unlink. Also, because we unlink
6300 : * before sending the SI messages, a backend that's currently starting cannot
6301 : * read the now-obsolete init file and then miss the SI messages that will
6302 : * force it to update its relcache entries. (This works because the backend
6303 : * startup sequence gets into the sinval array before trying to load the init
6304 : * file.)
6305 : *
6306 : * We take the lock and do the unlink in RelationCacheInitFilePreInvalidate,
6307 : * then release the lock in RelationCacheInitFilePostInvalidate. Caller must
6308 : * send any pending SI messages between those calls.
6309 : */
6310 : void
6311 38230 : RelationCacheInitFilePreInvalidate(void)
6312 : {
6313 : char localinitfname[MAXPGPATH];
6314 : char sharedinitfname[MAXPGPATH];
6315 :
6316 38230 : if (DatabasePath)
6317 38230 : snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6318 : DatabasePath, RELCACHE_INIT_FILENAME);
6319 38230 : snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6320 : RELCACHE_INIT_FILENAME);
6321 :
6322 38230 : LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6323 :
6324 : /*
6325 : * The files might not be there if no backend has been started since the
6326 : * last removal. But complain about failures other than ENOENT with
6327 : * ERROR. Fortunately, it's not too late to abort the transaction if we
6328 : * can't get rid of the would-be-obsolete init file.
6329 : */
6330 38230 : if (DatabasePath)
6331 38230 : unlink_initfile(localinitfname, ERROR);
6332 38230 : unlink_initfile(sharedinitfname, ERROR);
6333 38230 : }
6334 :
6335 : void
6336 38230 : RelationCacheInitFilePostInvalidate(void)
6337 : {
6338 38230 : LWLockRelease(RelCacheInitLock);
6339 38230 : }
6340 :
6341 : /*
6342 : * Remove the init files during postmaster startup.
6343 : *
6344 : * We used to keep the init files across restarts, but that is unsafe in PITR
6345 : * scenarios, and even in simple crash-recovery cases there are windows for
6346 : * the init files to become out-of-sync with the database. So now we just
6347 : * remove them during startup and expect the first backend launch to rebuild
6348 : * them. Of course, this has to happen in each database of the cluster.
6349 : */
6350 : void
6351 1548 : RelationCacheInitFileRemove(void)
6352 : {
6353 1548 : const char *tblspcdir = "pg_tblspc";
6354 : DIR *dir;
6355 : struct dirent *de;
6356 : char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6357 :
6358 1548 : snprintf(path, sizeof(path), "global/%s",
6359 : RELCACHE_INIT_FILENAME);
6360 1548 : unlink_initfile(path, LOG);
6361 :
6362 : /* Scan everything in the default tablespace */
6363 1548 : RelationCacheInitFileRemoveInDir("base");
6364 :
6365 : /* Scan the tablespace link directory to find non-default tablespaces */
6366 1548 : dir = AllocateDir(tblspcdir);
6367 :
6368 4714 : while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6369 : {
6370 3166 : if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6371 : {
6372 : /* Scan the tablespace dir for per-database dirs */
6373 70 : snprintf(path, sizeof(path), "%s/%s/%s",
6374 70 : tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6375 70 : RelationCacheInitFileRemoveInDir(path);
6376 : }
6377 : }
6378 :
6379 1548 : FreeDir(dir);
6380 1548 : }
6381 :
6382 : /* Process one per-tablespace directory for RelationCacheInitFileRemove */
6383 : static void
6384 1618 : RelationCacheInitFileRemoveInDir(const char *tblspcpath)
6385 : {
6386 : DIR *dir;
6387 : struct dirent *de;
6388 : char initfilename[MAXPGPATH * 2];
6389 :
6390 : /* Scan the tablespace directory to find per-database directories */
6391 1618 : dir = AllocateDir(tblspcpath);
6392 :
6393 8110 : while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
6394 : {
6395 6492 : if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6396 : {
6397 : /* Try to remove the init file in each database */
6398 3188 : snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6399 3188 : tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6400 3188 : unlink_initfile(initfilename, LOG);
6401 : }
6402 : }
6403 :
6404 1618 : FreeDir(dir);
6405 1618 : }
6406 :
6407 : static void
6408 81196 : unlink_initfile(const char *initfilename, int elevel)
6409 : {
6410 81196 : if (unlink(initfilename) < 0)
6411 : {
6412 : /* It might not be there, but log any error other than ENOENT */
6413 79592 : if (errno != ENOENT)
6414 0 : ereport(elevel,
6415 : (errcode_for_file_access(),
6416 : errmsg("could not remove cache file \"%s\": %m",
6417 : initfilename)));
6418 : }
6419 81196 : }
|