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