65#include "catalog/schemapg.h"
84#include "utils/fmgroids.h"
93#define RELCACHE_INIT_FILEMAGIC 0x573266
99#if defined(RECOVER_RELATION_BUILD_MEMORY) && (RECOVER_RELATION_BUILD_MEMORY != 0)
100#define MAYBE_RECOVER_RELATION_BUILD_MEMORY 1
102#define RECOVER_RELATION_BUILD_MEMORY 0
103#ifdef DISCARD_CACHES_ENABLED
104#define MAYBE_RECOVER_RELATION_BUILD_MEMORY 1
184#define MAX_EOXACT_LIST 32
189#define EOXactListAdd(rel) \
191 if (eoxact_list_len < MAX_EOXACT_LIST) \
192 eoxact_list[eoxact_list_len++] = (rel)->rd_id; \
194 eoxact_list_overflowed = true; \
209#define RelationCacheInsert(RELATION, replace_allowed) \
211 RelIdCacheEnt *hentry; bool found; \
212 hentry = (RelIdCacheEnt *) hash_search(RelationIdCache, \
213 &((RELATION)->rd_id), \
214 HASH_ENTER, &found); \
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)); \
228 hentry->reldesc = (RELATION); \
231#define RelationIdCacheLookup(ID, RELATION) \
233 RelIdCacheEnt *hentry; \
234 hentry = (RelIdCacheEnt *) hash_search(RelationIdCache, \
238 RELATION = hentry->reldesc; \
243#define RelationCacheDelete(RELATION) \
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); \
286#ifdef USE_ASSERT_CHECKING
287static void AssertPendingSyncConsistency(
Relation relation);
296static void formrdesc(
const char *relationName,
Oid relationReltype,
355 elog(
FATAL,
"cannot read pg_class without having selected a database");
380 if (force_non_historic)
400 return pg_class_tuple;
444 relation->
rd_rel = relationForm;
476 switch (relation->
rd_rel->relkind)
478 case RELKIND_RELATION:
479 case RELKIND_TOASTVALUE:
481 case RELKIND_MATVIEW:
482 case RELKIND_PARTITIONED_TABLE:
486 case RELKIND_PARTITIONED_INDEX:
535 relation->
rd_rel->reltype ? relation->
rd_rel->reltype : RECORDOID;
547 Anum_pg_attribute_attrelid,
551 Anum_pg_attribute_attnum,
562 AttributeRelidNumIndexId,
581 elog(
ERROR,
"invalid attribute number %d for relation \"%s\"",
591 if (attp->attnotnull)
593 if (attp->attgenerated == ATTRIBUTE_GENERATED_STORED)
599 if (attp->atthasmissing)
606 Anum_pg_attribute_attmissingval,
607 pg_attribute_desc->
rd_att,
617 if (attrmiss == NULL)
620 relation->
rd_rel->relnatts *
661 elog(
ERROR,
"pg_attribute catalog is missing %d attribute(s) for relation OID %u",
679 relation->
rd_rel->relchecks > 0)
690 if (relation->
rd_rel->relchecks > 0)
757 Anum_pg_rewrite_ev_class,
772 RewriteRelRulenameIndexId,
788 rule->ruleId = rewrite_form->oid;
790 rule->event = rewrite_form->ev_type -
'0';
791 rule->enabled = rewrite_form->ev_enabled;
792 rule->isInstead = rewrite_form->is_instead;
801 Anum_pg_rewrite_ev_action,
812 Anum_pg_rewrite_ev_qual,
831 relation->
rd_rel->relkind == RELKIND_VIEW &&
835 check_as_user = relation->
rd_rel->relowner;
851 if (numlocks >= maxlocks)
929 else if (rlock2 != NULL)
974 else if (policy2 != NULL)
991 if (rsdesc1 == NULL && rsdesc2 == NULL)
994 if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
995 (rsdesc1 == NULL && rsdesc2 != NULL))
1029 int in_progress_offset;
1050#ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1057 "RelationBuildDesc workspace",
1088#ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1106 Assert(relid == targetRelId);
1129 switch (relation->
rd_rel->relpersistence)
1131 case RELPERSISTENCE_UNLOGGED:
1132 case RELPERSISTENCE_PERMANENT:
1136 case RELPERSISTENCE_TEMP:
1164 elog(
ERROR,
"invalid relpersistence: %c",
1165 relation->
rd_rel->relpersistence);
1193 if (relation->
rd_rel->relkind == RELKIND_INDEX ||
1194 relation->
rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
1196 else if (RELKIND_HAS_TABLE_AM(relation->
rd_rel->relkind) ||
1197 relation->
rd_rel->relkind == RELKIND_SEQUENCE)
1199 else if (relation->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1218 if (relation->
rd_rel->relhasrules)
1226 if (relation->
rd_rel->relhastriggers)
1231 if (relation->
rd_rel->relrowsecurity)
1287#ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1312 if (!RELKIND_HAS_STORAGE(relation->
rd_rel->relkind))
1315 if (relation->
rd_rel->reltablespace)
1324 if (relation->
rd_rel->relfilenode)
1347 elog(
ERROR,
"could not find pg_class entry for %u",
1351 relation->
rd_rel->reltablespace = physrel->reltablespace;
1352 relation->
rd_rel->relfilenode = physrel->relfilenode;
1363 relation->
rd_rel->relisshared);
1365 elog(
ERROR,
"could not find relation mapping for relation \"%s\", OID %u",
1418 Datum indclassDatum;
1419 Datum indoptionDatum;
1438 elog(
ERROR,
"cache lookup failed for index %u",
1452 elog(
ERROR,
"cache lookup failed for access method %u",
1453 relation->
rd_rel->relam);
1460 elog(
ERROR,
"relnatts disagrees with indnatts for index %u",
1493 int nsupport = indnatts * amsupport;
1518 Anum_pg_index_indcollation,
1531 Anum_pg_index_indclass,
1544 amsupport, indnkeyatts);
1550 Anum_pg_index_indoption,
1593 for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
1605 opFamily[attIndex] = opcentry->
opcfamily;
1606 opcInType[attIndex] = opcentry->
opcintype;
1607 if (maxSupportNumber > 0)
1608 memcpy(&indexSupport[attIndex * maxSupportNumber],
1655 ctl.keysize =
sizeof(
Oid);
1668 opcentry->
valid =
false;
1686#ifdef DISCARD_CACHES_ENABLED
1688 opcentry->
valid =
false;
1691 if (opcentry->
valid)
1709 (operatorClassOid != OID_BTREE_OPS_OID &&
1710 operatorClassOid != INT2_BTREE_OPS_OID);
1719 Anum_pg_opclass_oid,
1730 opcentry->
opcfamily = opclassform->opcfamily;
1731 opcentry->
opcintype = opclassform->opcintype;
1734 elog(
ERROR,
"could not find tuple for opclass %u", operatorClassOid);
1746 Anum_pg_amproc_amprocfamily,
1750 Anum_pg_amproc_amproclefttype,
1754 Anum_pg_amproc_amprocrighttype,
1765 if (amprocform->amprocnum <= 0 ||
1767 elog(
ERROR,
"invalid amproc number %d for opclass %u",
1768 amprocform->amprocnum, operatorClassOid);
1778 opcentry->
valid =
true;
1802 if (relation->
rd_rel->relkind == RELKIND_SEQUENCE)
1830 elog(
ERROR,
"cache lookup failed for access method %u",
1831 relation->
rd_rel->relam);
1907 relation->
rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
1908 relation->
rd_rel->reltype = relationReltype;
1914 relation->
rd_rel->relisshared = isshared;
1916 relation->
rd_rel->reltablespace = GLOBALTABLESPACE_OID;
1919 relation->
rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
1922 relation->
rd_rel->relispopulated =
true;
1924 relation->
rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
1925 relation->
rd_rel->relpages = 0;
1926 relation->
rd_rel->reltuples = -1;
1927 relation->
rd_rel->relallvisible = 0;
1928 relation->
rd_rel->relkind = RELKIND_RELATION;
1947 has_not_null =
false;
1948 for (
i = 0;
i < natts;
i++)
1953 has_not_null |= attrs[
i].attnotnull;
2000 relation->
rd_rel->relam = HEAP_TABLE_AM_OID;
2009 relation->
rd_rel->relhasindex =
false;
2014 relation->
rd_rel->relhasindex =
true;
2110 .
name =
"relcache reference",
2198#ifdef RELCACHE_FORCE_RELEASE
2235 relation->
rd_rel->relkind == RELKIND_PARTITIONED_INDEX) &&
2264 elog(
ERROR,
"could not find pg_class tuple for index %u",
2293 elog(
ERROR,
"cache lookup failed for index %u",
2304 relation->
rd_index->indnullsnotdistinct =
index->indnullsnotdistinct;
2423 if (remember_tupdesc)
2559 if ((relation->
rd_rel->relkind == RELKIND_INDEX ||
2560 relation->
rd_rel->relkind == RELKIND_PARTITIONED_INDEX) &&
2642 elog(
ERROR,
"relation %u deleted while still in use", save_relid);
2656 keep_partkey = (relation->
rd_partkey != NULL);
2668#define SWAPFIELD(fldtype, fldname) \
2670 fldtype _tmp = newrel->fldname; \
2671 newrel->fldname = relation->fldname; \
2672 relation->fldname = _tmp; \
2856 elog(
ERROR,
"relation %u is still open", rid);
3011 rebuildFirstList =
lcons(relation, rebuildFirstList);
3013 rebuildFirstList =
lappend(rebuildFirstList, relation);
3015 rebuildList =
lcons(relation, rebuildList);
3017 rebuildList =
lappend(rebuildList, relation);
3031 foreach(l, rebuildFirstList)
3040 foreach(l, rebuildList)
3084#ifdef USE_ASSERT_CHECKING
3086AssertPendingSyncConsistency(
Relation relation)
3088 bool relcache_verdict =
3091 RELKIND_HAS_STORAGE(relation->
rd_rel->relkind)) ||
3127 rels =
palloc(maxrels *
sizeof(*rels));
3135 if (locallock->
nLocks <= 0)
3144 if (nrels >= maxrels)
3147 rels =
repalloc(rels, maxrels *
sizeof(*rels));
3154 AssertPendingSyncConsistency(idhentry->
reldesc);
3156 for (
i = 0;
i < nrels;
i++)
3219 if (idhentry != NULL)
3251 bool clear_relcache =
false;
3267#ifdef USE_ASSERT_CHECKING
3270 int expected_refcnt;
3317 elog(
WARNING,
"cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3357 mySubid, parentSubid);
3368 if (idhentry != NULL)
3370 mySubid, parentSubid);
3427 elog(
WARNING,
"cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3475 bool shared_relation,
3476 bool mapped_relation,
3477 char relpersistence,
3482 int natts = tupDesc->
natts;
3497 case DatabaseRelationId:
3498 case AuthIdRelationId:
3499 case AuthMemRelationId:
3500 case RelationRelationId:
3501 case AttributeRelationId:
3502 case ProcedureRelationId:
3503 case TypeRelationId:
3518 elog(
ERROR,
"shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3522 Assert(mapped_relation || !shared_relation);
3560 has_not_null =
false;
3561 for (
i = 0;
i < natts;
i++)
3566 datt->attidentity = satt->attidentity;
3567 datt->attgenerated = satt->attgenerated;
3568 datt->attnotnull = satt->attnotnull;
3569 has_not_null |= satt->attnotnull;
3587 rel->
rd_rel->relnamespace = relnamespace;
3589 rel->
rd_rel->relkind = relkind;
3590 rel->
rd_rel->relnatts = natts;
3593 rel->
rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3596 rel->
rd_rel->relpersistence = relpersistence;
3597 switch (relpersistence)
3599 case RELPERSISTENCE_UNLOGGED:
3600 case RELPERSISTENCE_PERMANENT:
3604 case RELPERSISTENCE_TEMP:
3610 elog(
ERROR,
"invalid relpersistence: %c", relpersistence);
3615 if (relkind == RELKIND_MATVIEW)
3616 rel->
rd_rel->relispopulated =
false;
3618 rel->
rd_rel->relispopulated =
true;
3622 (relkind == RELKIND_RELATION ||
3623 relkind == RELKIND_MATVIEW ||
3624 relkind == RELKIND_PARTITIONED_TABLE))
3625 rel->
rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3627 rel->
rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3634 rel->
rd_rel->relisshared = shared_relation;
3638 for (
i = 0;
i < natts;
i++)
3641 rel->
rd_rel->reltablespace = reltablespace;
3643 if (mapped_relation)
3650 rel->
rd_rel->relfilenode = relfilenumber;
3656 rel->
rd_rel->relam = accessmtd;
3665 if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_SEQUENCE)
3735 else if (relation->
rd_rel->relkind == RELKIND_INDEX)
3739 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3740 errmsg(
"index relfilenumber value not set when in binary upgrade mode")));
3745 else if (relation->
rd_rel->relkind == RELKIND_RELATION)
3749 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3750 errmsg(
"heap relfilenumber value not set when in binary upgrade mode")));
3757 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3758 errmsg(
"unexpected request for new relfilenumber in binary upgrade mode")));
3768 elog(
ERROR,
"could not find tuple for relation %u",
3815 newrlocator.
relNumber = newrelfilenumber;
3817 if (RELKIND_HAS_TABLE_AM(relation->
rd_rel->relkind))
3821 &freezeXid, &minmulti);
3823 else if (RELKIND_HAS_STORAGE(relation->
rd_rel->relkind))
3834 elog(
ERROR,
"relation \"%s\" does not have storage",
3853 Assert(classform->relfrozenxid == freezeXid);
3854 Assert(classform->relminmxid == minmulti);
3855 Assert(classform->relpersistence == persistence);
3868 relation->
rd_rel->relisshared,
3877 classform->relfilenode = newrelfilenumber;
3880 if (relation->
rd_rel->relkind != RELKIND_SEQUENCE)
3882 classform->relpages = 0;
3883 classform->reltuples = -1;
3884 classform->relallvisible = 0;
3886 classform->relfrozenxid = freezeXid;
3887 classform->relminmxid = minmulti;
3888 classform->relpersistence = persistence;
3943#define INITRELCACHESIZE 400
3960 ctl.keysize =
sizeof(
Oid);
4019 formrdesc(
"pg_database", DatabaseRelation_Rowtype_Id,
true,
4021 formrdesc(
"pg_authid", AuthIdRelation_Rowtype_Id,
true,
4023 formrdesc(
"pg_auth_members", AuthMemRelation_Rowtype_Id,
true,
4025 formrdesc(
"pg_shseclabel", SharedSecLabelRelation_Rowtype_Id,
true,
4027 formrdesc(
"pg_subscription", SubscriptionRelation_Rowtype_Id,
true,
4030#define NUM_CRITICAL_SHARED_RELS 5
4076 needNewCacheFile =
true;
4078 formrdesc(
"pg_class", RelationRelation_Rowtype_Id,
false,
4080 formrdesc(
"pg_attribute", AttributeRelation_Rowtype_Id,
false,
4082 formrdesc(
"pg_proc", ProcedureRelation_Rowtype_Id,
false,
4084 formrdesc(
"pg_type", TypeRelation_Rowtype_Id,
false,
4087#define NUM_CRITICAL_LOCAL_RELS 4
4124 RelationRelationId);
4126 AttributeRelationId);
4130 OperatorClassRelationId);
4132 AccessMethodProcedureRelationId);
4138#define NUM_CRITICAL_LOCAL_INDEXES 7
4158 DatabaseRelationId);
4160 DatabaseRelationId);
4168 SharedSecLabelRelationId);
4170#define NUM_CRITICAL_SHARED_INDEXES 6
4196 bool restart =
false;
4215 errcode(ERRCODE_UNDEFINED_OBJECT),
4244 elog(
ERROR,
"invalid relowner in pg_class entry for \"%s\"",
4262 relation->
rd_rel->relhasrules =
false;
4265 if (relation->
rd_rel->relhastriggers && relation->
trigdesc == NULL)
4269 relation->
rd_rel->relhastriggers =
false;
4290 (RELKIND_HAS_TABLE_AM(relation->
rd_rel->relkind) || relation->
rd_rel->relkind == RELKIND_SEQUENCE))
4313 if (needNewCacheFile)
4352 errmsg_internal(
"could not open critical system index %u", indexoid));
4386 for (
i = 0;
i < natts;
i++)
4409 if (pgclassdesc == NULL)
4422 if (pgindexdesc == NULL)
4455 Anum_pg_attrdef_adrelid,
4472 elog(
WARNING,
"unexpected pg_attrdef record found for attribute %d of relation \"%s\"",
4478 Anum_pg_attrdef_adbin,
4481 elog(
WARNING,
"null adbin for attribute %d of relation \"%s\"",
4488 attrdef[found].
adnum = adform->adnum;
4499 elog(
WARNING,
"%d pg_attrdef record(s) missing for relation \"%s\"",
4537 int ncheck = relation->
rd_rel->relchecks;
4551 Anum_pg_constraint_conrelid,
4566 if (conform->contype != CONSTRAINT_CHECK)
4570 if (found >= ncheck)
4572 elog(
WARNING,
"unexpected pg_constraint record found for relation \"%s\"",
4577 check[found].
ccenforced = conform->conenforced;
4578 check[found].
ccvalid = conform->convalidated;
4585 Anum_pg_constraint_conbin,
4586 conrel->
rd_att, &isnull);
4604 if (found != ncheck)
4605 elog(
WARNING,
"%d pg_constraint record(s) missing for relation \"%s\"",
4662 if (!relation->
rd_rel->relhastriggers &&
4663 relation->
rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
4676 Anum_pg_constraint_conrelid,
4690 if (constraint->contype != CONSTRAINT_FOREIGN)
4694 info->
conoid = constraint->oid;
4695 info->
conrelid = constraint->conrelid;
4696 info->
confrelid = constraint->confrelid;
4702 NULL, NULL, NULL, NULL);
4705 result =
lappend(result, info);
4764 char replident = relation->
rd_rel->relreplident;
4767 bool pkdeferrable =
false;
4784 Anum_pg_index_indrelid,
4802 if (!
index->indislive)
4814 if (!
index->indisunique ||
4828 if (
index->indisprimary &&
4829 (
index->indisvalid ||
4830 relation->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
4832 pkeyIndex =
index->indexrelid;
4833 pkdeferrable = !
index->indimmediate;
4836 if (!
index->indimmediate)
4839 if (!
index->indisvalid)
4843 if (
index->indisreplident)
4844 candidateIndex =
index->indexrelid;
4860 if (replident == REPLICA_IDENTITY_DEFAULT &&
OidIsValid(pkeyIndex) && !pkdeferrable)
4862 else if (replident == REPLICA_IDENTITY_INDEX &&
OidIsValid(candidateIndex))
4924 Anum_pg_statistic_ext_stxrelid,
5040 Anum_pg_index_indexprs,
5092 Anum_pg_index_indexprs,
5102 foreach(lc, rawExprs)
5153 Anum_pg_index_indpred,
5231 List *newindexoidlist;
5253 elog(
ERROR,
"unknown attrKind %u", attrKind);
5268 if (indexoidlist ==
NIL)
5292 pkindexattrs = NULL;
5293 idindexattrs = NULL;
5294 hotblockingattrs = NULL;
5295 summarizedattrs = NULL;
5296 foreach(l, indexoidlist)
5302 Node *indexExpressions;
5303 Node *indexPredicate;
5326 indexExpressions = NULL;
5333 indexPredicate = NULL;
5336 isKey = indexDesc->
rd_index->indisunique &&
5337 indexExpressions == NULL &&
5338 indexPredicate == NULL;
5341 isPK = (indexOid == relpkindex);
5344 isIDKey = (indexOid == relreplindex);
5352 attrs = &summarizedattrs;
5354 attrs = &hotblockingattrs;
5357 for (
i = 0;
i < indexDesc->
rd_index->indnatts;
i++)
5359 int attrnum = indexDesc->
rd_index->indkey.values[
i];
5380 if (isKey && i < indexDesc->rd_index->indnkeyatts)
5384 if (isPK && i < indexDesc->rd_index->indnkeyatts)
5388 if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
5410 if (
equal(indexoidlist, newindexoidlist) &&
5467 return pkindexattrs;
5469 return idindexattrs;
5471 return hotblockingattrs;
5473 return summarizedattrs;
5475 elog(
ERROR,
"unknown attrKind %u", attrKind);