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