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