LCOV - differential code coverage report
Current view: top level - src/backend/utils/cache - relcache.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 91.5 % 2113 1933 4 41 73 62 43 754 96 1040 71 791 4 61
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 79 79 53 6 20 55
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 86.7 % 30 26 4 26
Legend: Lines: hit not hit (60,120] days: 100.0 % 2 2 2
(120,180] days: 100.0 % 2 2 2
(240..) days: 91.5 % 2079 1903 41 73 62 43 754 66 1040 70 785
Function coverage date bins:
(240..) days: 59.4 % 133 79 53 6 20 54

 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 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a