PostgreSQL Source Code  git master
heap.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/multixact.h"
#include "access/relation.h"
#include "access/table.h"
#include "access/tableam.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.h"
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/objectaccess.h"
#include "catalog/partition.h"
#include "catalog/pg_am.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_foreign_table.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_partitioned_table.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_subscription_rel.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "catalog/storage.h"
#include "commands/tablecmds.h"
#include "commands/typecmds.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "parser/parsetree.h"
#include "partitioning/partdesc.h"
#include "pgstat.h"
#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
Include dependency graph for heap.c:

Go to the source code of this file.

Functions

static void AddNewRelationTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, Oid reloftype, Oid relowner, char relkind, TransactionId relfrozenxid, TransactionId relminmxid, Datum relacl, Datum reloptions)
 
static ObjectAddress AddNewRelationType (const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, Oid ownerid, Oid new_row_type, Oid new_array_type)
 
static void RelationRemoveInheritance (Oid relid)
 
static Oid StoreRelCheck (Relation rel, const char *ccname, Node *expr, bool is_validated, bool is_local, int inhcount, bool is_no_inherit, bool is_internal)
 
static void StoreConstraints (Relation rel, List *cooked_constraints, bool is_internal)
 
static bool MergeWithExistingConstraint (Relation rel, const char *ccname, Node *expr, bool allow_merge, bool is_local, bool is_initially_valid, bool is_no_inherit)
 
static void SetRelationNumChecks (Relation rel, int numchecks)
 
static NodecookConstraint (ParseState *pstate, Node *raw_constraint, char *relname)
 
const FormData_pg_attributeSystemAttributeDefinition (AttrNumber attno)
 
const FormData_pg_attributeSystemAttributeByName (const char *attname)
 
Relation heap_create (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, RelFileNumber relfilenumber, Oid accessmtd, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods, TransactionId *relfrozenxid, MultiXactId *relminmxid, bool create_storage)
 
void CheckAttributeNamesTypes (TupleDesc tupdesc, char relkind, int flags)
 
void CheckAttributeType (const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
 
void InsertPgAttributeTuples (Relation pg_attribute_rel, TupleDesc tupdesc, Oid new_rel_oid, Datum *attoptions, CatalogIndexState indstate)
 
static void AddNewAttributeTuples (Oid new_rel_oid, TupleDesc tupdesc, char relkind)
 
void InsertPgClassTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
 
Oid heap_create_with_catalog (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid reltypeid, Oid reloftypeid, Oid ownerid, Oid accessmtd, TupleDesc tupdesc, List *cooked_constraints, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, OnCommitAction oncommit, Datum reloptions, bool use_user_acl, bool allow_system_table_mods, bool is_internal, Oid relrewrite, ObjectAddress *typaddress)
 
void DeleteRelationTuple (Oid relid)
 
void DeleteAttributeTuples (Oid relid)
 
void DeleteSystemAttributeTuples (Oid relid)
 
void RemoveAttributeById (Oid relid, AttrNumber attnum)
 
void heap_drop_with_catalog (Oid relid)
 
void RelationClearMissing (Relation rel)
 
void SetAttrMissing (Oid relid, char *attname, char *value)
 
ListAddRelationNewConstraints (Relation rel, List *newColDefaults, List *newConstraints, bool allow_merge, bool is_local, bool is_internal, const char *queryString)
 
static bool check_nested_generated_walker (Node *node, void *context)
 
static void check_nested_generated (ParseState *pstate, Node *node)
 
NodecookDefault (ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname, char attgenerated)
 
void CopyStatistics (Oid fromrelid, Oid torelid)
 
void RemoveStatistics (Oid relid, AttrNumber attnum)
 
static void RelationTruncateIndexes (Relation heapRelation)
 
void heap_truncate (List *relids)
 
void heap_truncate_one_rel (Relation rel)
 
void heap_truncate_check_FKs (List *relations, bool tempTables)
 
Listheap_truncate_find_FKs (List *relationIds)
 
void StorePartitionKey (Relation rel, char strategy, int16 partnatts, AttrNumber *partattrs, List *partexprs, Oid *partopclass, Oid *partcollation)
 
void RemovePartitionKeyByRelId (Oid relid)
 
void StorePartitionBound (Relation rel, Relation parent, PartitionBoundSpec *bound)
 

Variables

Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid
 
Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid
 
RelFileNumber binary_upgrade_next_heap_pg_class_relfilenumber = InvalidRelFileNumber
 
RelFileNumber binary_upgrade_next_toast_pg_class_relfilenumber = InvalidRelFileNumber
 
static const FormData_pg_attribute a1
 
static const FormData_pg_attribute a2
 
static const FormData_pg_attribute a3
 
static const FormData_pg_attribute a4
 
static const FormData_pg_attribute a5
 
static const FormData_pg_attribute a6
 
static const FormData_pg_attributeSysAtt [] = {&a1, &a2, &a3, &a4, &a5, &a6}
 

Function Documentation

◆ AddNewAttributeTuples()

static void AddNewAttributeTuples ( Oid  new_rel_oid,
TupleDesc  tupdesc,
char  relkind 
)
static

Definition at line 804 of file heap.c.

807 {
808  Relation rel;
809  CatalogIndexState indstate;
810  int natts = tupdesc->natts;
811  ObjectAddress myself,
812  referenced;
813 
814  /*
815  * open pg_attribute and its indexes.
816  */
817  rel = table_open(AttributeRelationId, RowExclusiveLock);
818 
819  indstate = CatalogOpenIndexes(rel);
820 
821  /* set stats detail level to a sane default */
822  for (int i = 0; i < natts; i++)
823  tupdesc->attrs[i].attstattarget = -1;
824  InsertPgAttributeTuples(rel, tupdesc, new_rel_oid, NULL, indstate);
825 
826  /* add dependencies on their datatypes and collations */
827  for (int i = 0; i < natts; i++)
828  {
829  /* Add dependency info */
830  ObjectAddressSubSet(myself, RelationRelationId, new_rel_oid, i + 1);
831  ObjectAddressSet(referenced, TypeRelationId,
832  tupdesc->attrs[i].atttypid);
833  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
834 
835  /* The default collation is pinned, so don't bother recording it */
836  if (OidIsValid(tupdesc->attrs[i].attcollation) &&
837  tupdesc->attrs[i].attcollation != DEFAULT_COLLATION_OID)
838  {
839  ObjectAddressSet(referenced, CollationRelationId,
840  tupdesc->attrs[i].attcollation);
841  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
842  }
843  }
844 
845  /*
846  * Next we add the system attributes. Skip OID if rel has no OIDs. Skip
847  * all for a view or type relation. We don't bother with making datatype
848  * dependencies here, since presumably all these types are pinned.
849  */
850  if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
851  {
852  TupleDesc td;
853 
855 
856  InsertPgAttributeTuples(rel, td, new_rel_oid, NULL, indstate);
857  FreeTupleDesc(td);
858  }
859 
860  /*
861  * clean up
862  */
863  CatalogCloseIndexes(indstate);
864 
866 }
#define lengthof(array)
Definition: c.h:772
#define OidIsValid(objectId)
Definition: c.h:759
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
void InsertPgAttributeTuples(Relation pg_attribute_rel, TupleDesc tupdesc, Oid new_rel_oid, Datum *attoptions, CatalogIndexState indstate)
Definition: heap.c:697
static const FormData_pg_attribute * SysAtt[]
Definition: heap.c:231
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:61
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:43
int i
Definition: isn.c:73
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
Definition: objectaddress.h:33
FormData_pg_attribute
Definition: pg_attribute.h:193
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
FormData_pg_attribute attrs[FLEXIBLE_ARRAY_MEMBER]
Definition: tupdesc.h:87
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:309
TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs)
Definition: tupdesc.c:90

References TupleDescData::attrs, CatalogCloseIndexes(), CatalogOpenIndexes(), CreateTupleDesc(), DEPENDENCY_NORMAL, FormData_pg_attribute, FreeTupleDesc(), i, InsertPgAttributeTuples(), lengthof, TupleDescData::natts, ObjectAddressSet, ObjectAddressSubSet, OidIsValid, recordDependencyOn(), RowExclusiveLock, SysAtt, table_close(), and table_open().

Referenced by heap_create_with_catalog().

◆ AddNewRelationTuple()

static void AddNewRelationTuple ( Relation  pg_class_desc,
Relation  new_rel_desc,
Oid  new_rel_oid,
Oid  new_type_oid,
Oid  reloftype,
Oid  relowner,
char  relkind,
TransactionId  relfrozenxid,
TransactionId  relminmxid,
Datum  relacl,
Datum  reloptions 
)
static

Definition at line 955 of file heap.c.

966 {
967  Form_pg_class new_rel_reltup;
968 
969  /*
970  * first we update some of the information in our uncataloged relation's
971  * relation descriptor.
972  */
973  new_rel_reltup = new_rel_desc->rd_rel;
974 
975  /* The relation is empty */
976  new_rel_reltup->relpages = 0;
977  new_rel_reltup->reltuples = -1;
978  new_rel_reltup->relallvisible = 0;
979 
980  /* Sequences always have a known size */
981  if (relkind == RELKIND_SEQUENCE)
982  {
983  new_rel_reltup->relpages = 1;
984  new_rel_reltup->reltuples = 1;
985  }
986 
987  new_rel_reltup->relfrozenxid = relfrozenxid;
988  new_rel_reltup->relminmxid = relminmxid;
989  new_rel_reltup->relowner = relowner;
990  new_rel_reltup->reltype = new_type_oid;
991  new_rel_reltup->reloftype = reloftype;
992 
993  /* relispartition is always set by updating this tuple later */
994  new_rel_reltup->relispartition = false;
995 
996  /* fill rd_att's type ID with something sane even if reltype is zero */
997  new_rel_desc->rd_att->tdtypeid = new_type_oid ? new_type_oid : RECORDOID;
998  new_rel_desc->rd_att->tdtypmod = -1;
999 
1000  /* Now build and insert the tuple */
1001  InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid,
1002  relacl, reloptions);
1003 }
void InsertPgClassTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
Definition: heap.c:882
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
TupleDesc rd_att
Definition: rel.h:112
Form_pg_class rd_rel
Definition: rel.h:111
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82

References InsertPgClassTuple(), RelationData::rd_att, RelationData::rd_rel, TupleDescData::tdtypeid, and TupleDescData::tdtypmod.

Referenced by heap_create_with_catalog().

◆ AddNewRelationType()

static ObjectAddress AddNewRelationType ( const char *  typeName,
Oid  typeNamespace,
Oid  new_rel_oid,
char  new_rel_kind,
Oid  ownerid,
Oid  new_row_type,
Oid  new_array_type 
)
static

Definition at line 1013 of file heap.c.

1020 {
1021  return
1022  TypeCreate(new_row_type, /* optional predetermined OID */
1023  typeName, /* type name */
1024  typeNamespace, /* type namespace */
1025  new_rel_oid, /* relation oid */
1026  new_rel_kind, /* relation kind */
1027  ownerid, /* owner's ID */
1028  -1, /* internal size (varlena) */
1029  TYPTYPE_COMPOSITE, /* type-type (composite) */
1030  TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
1031  false, /* composite types are never preferred */
1032  DEFAULT_TYPDELIM, /* default array delimiter */
1033  F_RECORD_IN, /* input procedure */
1034  F_RECORD_OUT, /* output procedure */
1035  F_RECORD_RECV, /* receive procedure */
1036  F_RECORD_SEND, /* send procedure */
1037  InvalidOid, /* typmodin procedure - none */
1038  InvalidOid, /* typmodout procedure - none */
1039  InvalidOid, /* analyze procedure - default */
1040  InvalidOid, /* subscript procedure - none */
1041  InvalidOid, /* array element type - irrelevant */
1042  false, /* this is not an array type */
1043  new_array_type, /* array type if any */
1044  InvalidOid, /* domain base type - irrelevant */
1045  NULL, /* default value - none */
1046  NULL, /* default binary representation */
1047  false, /* passed by reference */
1048  TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1049  TYPSTORAGE_EXTENDED, /* fully TOASTable */
1050  -1, /* typmod */
1051  0, /* array dimensions for typBaseType */
1052  false, /* Type NOT NULL */
1053  InvalidOid); /* rowtypes never have a collation */
1054 }
ObjectAddress TypeCreate(Oid newTypeOid, const char *typeName, Oid typeNamespace, Oid relationOid, char relationKind, Oid ownerId, int16 internalSize, char typeType, char typeCategory, bool typePreferred, char typDelim, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid subscriptProcedure, Oid elementType, bool isImplicitArray, Oid arrayType, Oid baseType, const char *defaultTypeValue, char *defaultTypeBin, bool passedByValue, char alignment, char storage, int32 typeMod, int32 typNDims, bool typeNotNull, Oid typeCollation)
Definition: pg_type.c:196
#define InvalidOid
Definition: postgres_ext.h:36
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22

References DEFAULT_TYPDELIM, InvalidOid, and TypeCreate().

Referenced by heap_create_with_catalog().

◆ AddRelationNewConstraints()

List* AddRelationNewConstraints ( Relation  rel,
List newColDefaults,
List newConstraints,
bool  allow_merge,
bool  is_local,
bool  is_internal,
const char *  queryString 
)

Definition at line 2246 of file heap.c.

2253 {
2254  List *cookedConstraints = NIL;
2255  TupleDesc tupleDesc;
2256  TupleConstr *oldconstr;
2257  int numoldchecks;
2258  ParseState *pstate;
2259  ParseNamespaceItem *nsitem;
2260  int numchecks;
2261  List *checknames;
2262  ListCell *cell;
2263  Node *expr;
2264  CookedConstraint *cooked;
2265 
2266  /*
2267  * Get info about existing constraints.
2268  */
2269  tupleDesc = RelationGetDescr(rel);
2270  oldconstr = tupleDesc->constr;
2271  if (oldconstr)
2272  numoldchecks = oldconstr->num_check;
2273  else
2274  numoldchecks = 0;
2275 
2276  /*
2277  * Create a dummy ParseState and insert the target relation as its sole
2278  * rangetable entry. We need a ParseState for transformExpr.
2279  */
2280  pstate = make_parsestate(NULL);
2281  pstate->p_sourcetext = queryString;
2282  nsitem = addRangeTableEntryForRelation(pstate,
2283  rel,
2285  NULL,
2286  false,
2287  true);
2288  addNSItemToQuery(pstate, nsitem, true, true, true);
2289 
2290  /*
2291  * Process column default expressions.
2292  */
2293  foreach(cell, newColDefaults)
2294  {
2295  RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
2296  Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
2297  Oid defOid;
2298 
2299  expr = cookDefault(pstate, colDef->raw_default,
2300  atp->atttypid, atp->atttypmod,
2301  NameStr(atp->attname),
2302  atp->attgenerated);
2303 
2304  /*
2305  * If the expression is just a NULL constant, we do not bother to make
2306  * an explicit pg_attrdef entry, since the default behavior is
2307  * equivalent. This applies to column defaults, but not for
2308  * generation expressions.
2309  *
2310  * Note a nonobvious property of this test: if the column is of a
2311  * domain type, what we'll get is not a bare null Const but a
2312  * CoerceToDomain expr, so we will not discard the default. This is
2313  * critical because the column default needs to be retained to
2314  * override any default that the domain might have.
2315  */
2316  if (expr == NULL ||
2317  (!colDef->generated &&
2318  IsA(expr, Const) &&
2319  castNode(Const, expr)->constisnull))
2320  continue;
2321 
2322  /* If the DEFAULT is volatile we cannot use a missing value */
2323  if (colDef->missingMode && contain_volatile_functions((Node *) expr))
2324  colDef->missingMode = false;
2325 
2326  defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal,
2327  colDef->missingMode);
2328 
2329  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2330  cooked->contype = CONSTR_DEFAULT;
2331  cooked->conoid = defOid;
2332  cooked->name = NULL;
2333  cooked->attnum = colDef->attnum;
2334  cooked->expr = expr;
2335  cooked->skip_validation = false;
2336  cooked->is_local = is_local;
2337  cooked->inhcount = is_local ? 0 : 1;
2338  cooked->is_no_inherit = false;
2339  cookedConstraints = lappend(cookedConstraints, cooked);
2340  }
2341 
2342  /*
2343  * Process constraint expressions.
2344  */
2345  numchecks = numoldchecks;
2346  checknames = NIL;
2347  foreach(cell, newConstraints)
2348  {
2349  Constraint *cdef = (Constraint *) lfirst(cell);
2350  char *ccname;
2351  Oid constrOid;
2352 
2353  if (cdef->contype != CONSTR_CHECK)
2354  continue;
2355 
2356  if (cdef->raw_expr != NULL)
2357  {
2358  Assert(cdef->cooked_expr == NULL);
2359 
2360  /*
2361  * Transform raw parsetree to executable expression, and verify
2362  * it's valid as a CHECK constraint.
2363  */
2364  expr = cookConstraint(pstate, cdef->raw_expr,
2366  }
2367  else
2368  {
2369  Assert(cdef->cooked_expr != NULL);
2370 
2371  /*
2372  * Here, we assume the parser will only pass us valid CHECK
2373  * expressions, so we do no particular checking.
2374  */
2375  expr = stringToNode(cdef->cooked_expr);
2376  }
2377 
2378  /*
2379  * Check name uniqueness, or generate a name if none was given.
2380  */
2381  if (cdef->conname != NULL)
2382  {
2383  ListCell *cell2;
2384 
2385  ccname = cdef->conname;
2386  /* Check against other new constraints */
2387  /* Needed because we don't do CommandCounterIncrement in loop */
2388  foreach(cell2, checknames)
2389  {
2390  if (strcmp((char *) lfirst(cell2), ccname) == 0)
2391  ereport(ERROR,
2393  errmsg("check constraint \"%s\" already exists",
2394  ccname)));
2395  }
2396 
2397  /* save name for future checks */
2398  checknames = lappend(checknames, ccname);
2399 
2400  /*
2401  * Check against pre-existing constraints. If we are allowed to
2402  * merge with an existing constraint, there's no more to do here.
2403  * (We omit the duplicate constraint from the result, which is
2404  * what ATAddCheckConstraint wants.)
2405  */
2406  if (MergeWithExistingConstraint(rel, ccname, expr,
2407  allow_merge, is_local,
2408  cdef->initially_valid,
2409  cdef->is_no_inherit))
2410  continue;
2411  }
2412  else
2413  {
2414  /*
2415  * When generating a name, we want to create "tab_col_check" for a
2416  * column constraint and "tab_check" for a table constraint. We
2417  * no longer have any info about the syntactic positioning of the
2418  * constraint phrase, so we approximate this by seeing whether the
2419  * expression references more than one column. (If the user
2420  * played by the rules, the result is the same...)
2421  *
2422  * Note: pull_var_clause() doesn't descend into sublinks, but we
2423  * eliminated those above; and anyway this only needs to be an
2424  * approximate answer.
2425  */
2426  List *vars;
2427  char *colname;
2428 
2429  vars = pull_var_clause(expr, 0);
2430 
2431  /* eliminate duplicates */
2432  vars = list_union(NIL, vars);
2433 
2434  if (list_length(vars) == 1)
2435  colname = get_attname(RelationGetRelid(rel),
2436  ((Var *) linitial(vars))->varattno,
2437  true);
2438  else
2439  colname = NULL;
2440 
2442  colname,
2443  "check",
2444  RelationGetNamespace(rel),
2445  checknames);
2446 
2447  /* save name for future checks */
2448  checknames = lappend(checknames, ccname);
2449  }
2450 
2451  /*
2452  * OK, store it.
2453  */
2454  constrOid =
2455  StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
2456  is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
2457 
2458  numchecks++;
2459 
2460  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2461  cooked->contype = CONSTR_CHECK;
2462  cooked->conoid = constrOid;
2463  cooked->name = ccname;
2464  cooked->attnum = 0;
2465  cooked->expr = expr;
2466  cooked->skip_validation = cdef->skip_validation;
2467  cooked->is_local = is_local;
2468  cooked->inhcount = is_local ? 0 : 1;
2469  cooked->is_no_inherit = cdef->is_no_inherit;
2470  cookedConstraints = lappend(cookedConstraints, cooked);
2471  }
2472 
2473  /*
2474  * Update the count of constraints in the relation's pg_class tuple. We do
2475  * this even if there was no change, in order to ensure that an SI update
2476  * message is sent out for the pg_class tuple, which will force other
2477  * backends to rebuild their relcache entries for the rel. (This is
2478  * critical if we added defaults but not constraints.)
2479  */
2480  SetRelationNumChecks(rel, numchecks);
2481 
2482  return cookedConstraints;
2483 }
#define NameStr(name)
Definition: c.h:730
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:483
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
static Oid StoreRelCheck(Relation rel, const char *ccname, Node *expr, bool is_validated, bool is_local, int inhcount, bool is_no_inherit, bool is_internal)
Definition: heap.c:2064
static bool MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, bool allow_merge, bool is_local, bool is_initially_valid, bool is_no_inherit)
Definition: heap.c:2496
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname, char attgenerated)
Definition: heap.c:2745
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2651
static Node * cookConstraint(ParseState *pstate, Node *raw_constraint, char *relname)
Definition: heap.c:2820
Assert(fmt[strlen(fmt) - 1] !='\n')
List * list_union(const List *list1, const List *list2)
Definition: list.c:1065
List * lappend(List *list, void *datum)
Definition: list.c:338
#define AccessShareLock
Definition: lockdefs.h:36
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:826
void * palloc(Size size)
Definition: mcxt.c:1226
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
#define castNode(_type_, nodeptr)
Definition: nodes.h:197
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
@ CONSTR_DEFAULT
Definition: parsenodes.h:2525
@ CONSTR_CHECK
Definition: parsenodes.h:2528
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal, bool add_column_mode)
Definition: pg_attrdef.c:46
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
char * ChooseConstraintName(const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define linitial(l)
Definition: pg_list.h:178
unsigned int Oid
Definition: postgres_ext.h:31
void * stringToNode(const char *str)
Definition: read.c:90
#define RelationGetRelid(relation)
Definition: rel.h:504
#define RelationGetDescr(relation)
Definition: rel.h:530
#define RelationGetRelationName(relation)
Definition: rel.h:538
#define RelationGetNamespace(relation)
Definition: rel.h:545
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
ConstrType contype
Definition: parsenodes.h:2556
bool is_no_inherit
Definition: parsenodes.h:2565
char * cooked_expr
Definition: parsenodes.h:2567
bool initially_valid
Definition: parsenodes.h:2604
bool skip_validation
Definition: parsenodes.h:2603
Node * raw_expr
Definition: parsenodes.h:2566
char * conname
Definition: parsenodes.h:2559
Oid conoid
Definition: heap.h:38
char * name
Definition: heap.h:39
AttrNumber attnum
Definition: heap.h:40
bool skip_validation
Definition: heap.h:42
bool is_no_inherit
Definition: heap.h:45
int inhcount
Definition: heap.h:44
bool is_local
Definition: heap.h:43
ConstrType contype
Definition: heap.h:37
Node * expr
Definition: heap.h:41
Definition: pg_list.h:54
Definition: nodes.h:129
const char * p_sourcetext
Definition: parse_node.h:192
Node * raw_default
Definition: heap.h:30
AttrNumber attnum
Definition: heap.h:29
char generated
Definition: heap.h:32
bool missingMode
Definition: heap.h:31
uint16 num_check
Definition: tupdesc.h:43
TupleConstr * constr
Definition: tupdesc.h:85
Definition: primnodes.h:226
Definition: regcomp.c:281
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
List * pull_var_clause(Node *node, int flags)
Definition: var.c:607

References AccessShareLock, addNSItemToQuery(), addRangeTableEntryForRelation(), Assert(), RawColumnDefault::attnum, CookedConstraint::attnum, castNode, ChooseConstraintName(), Constraint::conname, CookedConstraint::conoid, TupleDescData::constr, CONSTR_CHECK, CONSTR_DEFAULT, contain_volatile_functions(), CookedConstraint::contype, Constraint::contype, cookConstraint(), cookDefault(), Constraint::cooked_expr, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, CookedConstraint::expr, RawColumnDefault::generated, get_attname(), CookedConstraint::inhcount, Constraint::initially_valid, CookedConstraint::is_local, CookedConstraint::is_no_inherit, Constraint::is_no_inherit, IsA, lappend(), lfirst, linitial, list_length(), list_union(), make_parsestate(), MergeWithExistingConstraint(), RawColumnDefault::missingMode, CookedConstraint::name, NameStr, NIL, TupleConstr::num_check, ParseState::p_sourcetext, palloc(), pull_var_clause(), RawColumnDefault::raw_default, Constraint::raw_expr, RelationData::rd_att, RelationGetDescr, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, SetRelationNumChecks(), CookedConstraint::skip_validation, Constraint::skip_validation, StoreAttrDefault(), StoreRelCheck(), stringToNode(), and TupleDescAttr.

Referenced by ATAddCheckConstraint(), ATExecAddColumn(), ATExecColumnDefault(), and DefineRelation().

◆ check_nested_generated()

static void check_nested_generated ( ParseState pstate,
Node node 
)
static

Definition at line 2727 of file heap.c.

2728 {
2729  check_nested_generated_walker(node, pstate);
2730 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:2685

References check_nested_generated_walker().

Referenced by cookDefault().

◆ check_nested_generated_walker()

static bool check_nested_generated_walker ( Node node,
void *  context 
)
static

Definition at line 2685 of file heap.c.

2686 {
2687  ParseState *pstate = context;
2688 
2689  if (node == NULL)
2690  return false;
2691  else if (IsA(node, Var))
2692  {
2693  Var *var = (Var *) node;
2694  Oid relid;
2696 
2697  relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
2698  if (!OidIsValid(relid))
2699  return false; /* XXX shouldn't we raise an error? */
2700 
2701  attnum = var->varattno;
2702 
2703  if (attnum > 0 && get_attgenerated(relid, attnum))
2704  ereport(ERROR,
2705  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2706  errmsg("cannot use generated column \"%s\" in column generation expression",
2707  get_attname(relid, attnum, false)),
2708  errdetail("A generated column cannot reference another generated column."),
2709  parser_errposition(pstate, var->location)));
2710  /* A whole-row Var is necessarily self-referential, so forbid it */
2711  if (attnum == 0)
2712  ereport(ERROR,
2713  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2714  errmsg("cannot use whole-row variable in column generation expression"),
2715  errdetail("This would cause the generated column to depend on its own value."),
2716  parser_errposition(pstate, var->location)));
2717  /* System columns were already checked in the parser */
2718 
2719  return false;
2720  }
2721  else
2723  (void *) context);
2724 }
int16 AttrNumber
Definition: attnum.h:21
int errdetail(const char *fmt,...)
Definition: elog.c:1202
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:914
#define expression_tree_walker(n, w, c)
Definition: nodeFuncs.h:151
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
int16 attnum
Definition: pg_attribute.h:74
List * p_rtable
Definition: parse_node.h:193
AttrNumber varattno
Definition: primnodes.h:238
int varno
Definition: primnodes.h:233
int location
Definition: primnodes.h:271

References attnum, ereport, errcode(), errdetail(), errmsg(), ERROR, expression_tree_walker, get_attgenerated(), get_attname(), IsA, Var::location, OidIsValid, ParseState::p_rtable, parser_errposition(), rt_fetch, Var::varattno, and Var::varno.

Referenced by check_nested_generated().

◆ CheckAttributeNamesTypes()

void CheckAttributeNamesTypes ( TupleDesc  tupdesc,
char  relkind,
int  flags 
)

Definition at line 455 of file heap.c.

457 {
458  int i;
459  int j;
460  int natts = tupdesc->natts;
461 
462  /* Sanity check on column count */
463  if (natts < 0 || natts > MaxHeapAttributeNumber)
464  ereport(ERROR,
465  (errcode(ERRCODE_TOO_MANY_COLUMNS),
466  errmsg("tables can have at most %d columns",
468 
469  /*
470  * first check for collision with system attribute names
471  *
472  * Skip this for a view or type relation, since those don't have system
473  * attributes.
474  */
475  if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
476  {
477  for (i = 0; i < natts; i++)
478  {
479  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
480 
481  if (SystemAttributeByName(NameStr(attr->attname)) != NULL)
482  ereport(ERROR,
483  (errcode(ERRCODE_DUPLICATE_COLUMN),
484  errmsg("column name \"%s\" conflicts with a system column name",
485  NameStr(attr->attname))));
486  }
487  }
488 
489  /*
490  * next check for repeated attribute names
491  */
492  for (i = 1; i < natts; i++)
493  {
494  for (j = 0; j < i; j++)
495  {
496  if (strcmp(NameStr(TupleDescAttr(tupdesc, j)->attname),
497  NameStr(TupleDescAttr(tupdesc, i)->attname)) == 0)
498  ereport(ERROR,
499  (errcode(ERRCODE_DUPLICATE_COLUMN),
500  errmsg("column name \"%s\" specified more than once",
501  NameStr(TupleDescAttr(tupdesc, j)->attname))));
502  }
503  }
504 
505  /*
506  * next check the attribute types
507  */
508  for (i = 0; i < natts; i++)
509  {
511  TupleDescAttr(tupdesc, i)->atttypid,
512  TupleDescAttr(tupdesc, i)->attcollation,
513  NIL, /* assume we're creating a new rowtype */
514  flags);
515  }
516 }
void CheckAttributeType(const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
Definition: heap.c:547
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
Definition: heap.c:251
#define MaxHeapAttributeNumber
Definition: htup_details.h:48
int j
Definition: isn.c:74
NameData attname
Definition: pg_attribute.h:41

References attname, CheckAttributeType(), ereport, errcode(), errmsg(), ERROR, i, j, MaxHeapAttributeNumber, NameStr, TupleDescData::natts, NIL, SystemAttributeByName(), and TupleDescAttr.

Referenced by addRangeTableEntryForFunction(), and heap_create_with_catalog().

◆ CheckAttributeType()

void CheckAttributeType ( const char *  attname,
Oid  atttypid,
Oid  attcollation,
List containing_rowtypes,
int  flags 
)

Definition at line 547 of file heap.c.

551 {
552  char att_typtype = get_typtype(atttypid);
553  Oid att_typelem;
554 
555  if (att_typtype == TYPTYPE_PSEUDO)
556  {
557  /*
558  * We disallow pseudo-type columns, with the exception of ANYARRAY,
559  * RECORD, and RECORD[] when the caller says that those are OK.
560  *
561  * We don't need to worry about recursive containment for RECORD and
562  * RECORD[] because (a) no named composite type should be allowed to
563  * contain those, and (b) two "anonymous" record types couldn't be
564  * considered to be the same type, so infinite recursion isn't
565  * possible.
566  */
567  if (!((atttypid == ANYARRAYOID && (flags & CHKATYPE_ANYARRAY)) ||
568  (atttypid == RECORDOID && (flags & CHKATYPE_ANYRECORD)) ||
569  (atttypid == RECORDARRAYOID && (flags & CHKATYPE_ANYRECORD))))
570  {
571  if (flags & CHKATYPE_IS_PARTKEY)
572  ereport(ERROR,
573  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
574  /* translator: first %s is an integer not a name */
575  errmsg("partition key column %s has pseudo-type %s",
576  attname, format_type_be(atttypid))));
577  else
578  ereport(ERROR,
579  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
580  errmsg("column \"%s\" has pseudo-type %s",
581  attname, format_type_be(atttypid))));
582  }
583  }
584  else if (att_typtype == TYPTYPE_DOMAIN)
585  {
586  /*
587  * If it's a domain, recurse to check its base type.
588  */
589  CheckAttributeType(attname, getBaseType(atttypid), attcollation,
590  containing_rowtypes,
591  flags);
592  }
593  else if (att_typtype == TYPTYPE_COMPOSITE)
594  {
595  /*
596  * For a composite type, recurse into its attributes.
597  */
598  Relation relation;
599  TupleDesc tupdesc;
600  int i;
601 
602  /*
603  * Check for self-containment. Eventually we might be able to allow
604  * this (just return without complaint, if so) but it's not clear how
605  * many other places would require anti-recursion defenses before it
606  * would be safe to allow tables to contain their own rowtype.
607  */
608  if (list_member_oid(containing_rowtypes, atttypid))
609  ereport(ERROR,
610  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
611  errmsg("composite type %s cannot be made a member of itself",
612  format_type_be(atttypid))));
613 
614  containing_rowtypes = lappend_oid(containing_rowtypes, atttypid);
615 
616  relation = relation_open(get_typ_typrelid(atttypid), AccessShareLock);
617 
618  tupdesc = RelationGetDescr(relation);
619 
620  for (i = 0; i < tupdesc->natts; i++)
621  {
622  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
623 
624  if (attr->attisdropped)
625  continue;
626  CheckAttributeType(NameStr(attr->attname),
627  attr->atttypid, attr->attcollation,
628  containing_rowtypes,
629  flags & ~CHKATYPE_IS_PARTKEY);
630  }
631 
632  relation_close(relation, AccessShareLock);
633 
634  containing_rowtypes = list_delete_last(containing_rowtypes);
635  }
636  else if (att_typtype == TYPTYPE_RANGE)
637  {
638  /*
639  * If it's a range, recurse to check its subtype.
640  */
642  get_range_collation(atttypid),
643  containing_rowtypes,
644  flags);
645  }
646  else if (OidIsValid((att_typelem = get_element_type(atttypid))))
647  {
648  /*
649  * Must recurse into array types, too, in case they are composite.
650  */
651  CheckAttributeType(attname, att_typelem, attcollation,
652  containing_rowtypes,
653  flags);
654  }
655 
656  /*
657  * This might not be strictly invalid per SQL standard, but it is pretty
658  * useless, and it cannot be dumped, so we must disallow it.
659  */
660  if (!OidIsValid(attcollation) && type_is_collatable(atttypid))
661  {
662  if (flags & CHKATYPE_IS_PARTKEY)
663  ereport(ERROR,
664  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
665  /* translator: first %s is an integer not a name */
666  errmsg("no collation was derived for partition key column %s with collatable type %s",
667  attname, format_type_be(atttypid)),
668  errhint("Use the COLLATE clause to set the collation explicitly.")));
669  else
670  ereport(ERROR,
671  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
672  errmsg("no collation was derived for column \"%s\" with collatable type %s",
673  attname, format_type_be(atttypid)),
674  errhint("Use the COLLATE clause to set the collation explicitly.")));
675  }
676 }
int errhint(const char *fmt,...)
Definition: elog.c:1316
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
#define CHKATYPE_ANYRECORD
Definition: heap.h:24
#define CHKATYPE_ANYARRAY
Definition: heap.h:23
#define CHKATYPE_IS_PARTKEY
Definition: heap.h:25
List * lappend_oid(List *list, Oid datum)
Definition: list.c:374
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:721
List * list_delete_last(List *list)
Definition: list.c:956
Oid get_range_subtype(Oid rangeOid)
Definition: lsyscache.c:3365
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2717
Oid get_range_collation(Oid rangeOid)
Definition: lsyscache.c:3391
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:3039
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2689
char get_typtype(Oid typid)
Definition: lsyscache.c:2587
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2479
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48

References AccessShareLock, attname, CHKATYPE_ANYARRAY, CHKATYPE_ANYRECORD, CHKATYPE_IS_PARTKEY, ereport, errcode(), errhint(), errmsg(), ERROR, format_type_be(), get_element_type(), get_range_collation(), get_range_subtype(), get_typ_typrelid(), get_typtype(), getBaseType(), i, lappend_oid(), list_delete_last(), list_member_oid(), NameStr, TupleDescData::natts, OidIsValid, relation_close(), relation_open(), RelationGetDescr, TupleDescAttr, and type_is_collatable().

Referenced by ATExecAddColumn(), ATPrepAlterColumnType(), CheckAttributeNamesTypes(), ComputePartitionAttrs(), and ConstructTupleDescriptor().

◆ cookConstraint()

static Node * cookConstraint ( ParseState pstate,
Node raw_constraint,
char *  relname 
)
static

Definition at line 2820 of file heap.c.

2823 {
2824  Node *expr;
2825 
2826  /*
2827  * Transform raw parsetree to executable expression.
2828  */
2829  expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
2830 
2831  /*
2832  * Make sure it yields a boolean result.
2833  */
2834  expr = coerce_to_boolean(pstate, expr, "CHECK");
2835 
2836  /*
2837  * Take care of collations.
2838  */
2839  assign_expr_collations(pstate, expr);
2840 
2841  /*
2842  * Make sure no outside relations are referred to (this is probably dead
2843  * code now that add_missing_from is history).
2844  */
2845  if (list_length(pstate->p_rtable) != 1)
2846  ereport(ERROR,
2847  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2848  errmsg("only table \"%s\" can be referenced in check constraint",
2849  relname)));
2850 
2851  return expr;
2852 }
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:106
@ EXPR_KIND_CHECK_CONSTRAINT
Definition: parse_node.h:67
NameData relname
Definition: pg_class.h:38

References assign_expr_collations(), coerce_to_boolean(), ereport, errcode(), errmsg(), ERROR, EXPR_KIND_CHECK_CONSTRAINT, list_length(), ParseState::p_rtable, relname, and transformExpr().

Referenced by AddRelationNewConstraints().

◆ cookDefault()

Node* cookDefault ( ParseState pstate,
Node raw_default,
Oid  atttypid,
int32  atttypmod,
const char *  attname,
char  attgenerated 
)

Definition at line 2745 of file heap.c.

2751 {
2752  Node *expr;
2753 
2754  Assert(raw_default != NULL);
2755 
2756  /*
2757  * Transform raw parsetree to executable expression.
2758  */
2759  expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
2760 
2761  if (attgenerated)
2762  {
2763  check_nested_generated(pstate, expr);
2764 
2765  if (contain_mutable_functions(expr))
2766  ereport(ERROR,
2767  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2768  errmsg("generation expression is not immutable")));
2769  }
2770  else
2771  {
2772  /*
2773  * For a default expression, transformExpr() should have rejected
2774  * column references.
2775  */
2776  Assert(!contain_var_clause(expr));
2777  }
2778 
2779  /*
2780  * Coerce the expression to the correct type and typmod, if given. This
2781  * should match the parser's processing of non-defaulted expressions ---
2782  * see transformAssignedExpr().
2783  */
2784  if (OidIsValid(atttypid))
2785  {
2786  Oid type_id = exprType(expr);
2787 
2788  expr = coerce_to_target_type(pstate, expr, type_id,
2789  atttypid, atttypmod,
2792  -1);
2793  if (expr == NULL)
2794  ereport(ERROR,
2795  (errcode(ERRCODE_DATATYPE_MISMATCH),
2796  errmsg("column \"%s\" is of type %s"
2797  " but default expression is of type %s",
2798  attname,
2799  format_type_be(atttypid),
2800  format_type_be(type_id)),
2801  errhint("You will need to rewrite or cast the expression.")));
2802  }
2803 
2804  /*
2805  * Finally, take care of collations in the finished expression.
2806  */
2807  assign_expr_collations(pstate, expr);
2808 
2809  return expr;
2810 }
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:367
static void check_nested_generated(ParseState *pstate, Node *node)
Definition: heap.c:2727
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:43
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:78
@ EXPR_KIND_COLUMN_DEFAULT
Definition: parse_node.h:69
@ EXPR_KIND_GENERATED_COLUMN
Definition: parse_node.h:82
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:663
@ COERCION_ASSIGNMENT
Definition: primnodes.h:642
bool contain_var_clause(Node *node)
Definition: var.c:403

References Assert(), assign_expr_collations(), attname, check_nested_generated(), COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, contain_mutable_functions(), contain_var_clause(), ereport, errcode(), errhint(), errmsg(), ERROR, EXPR_KIND_COLUMN_DEFAULT, EXPR_KIND_GENERATED_COLUMN, exprType(), format_type_be(), OidIsValid, and transformExpr().

Referenced by AddRelationNewConstraints(), AlterDomainDefault(), and DefineDomain().

◆ CopyStatistics()

void CopyStatistics ( Oid  fromrelid,
Oid  torelid 
)

Definition at line 2858 of file heap.c.

2859 {
2860  HeapTuple tup;
2861  SysScanDesc scan;
2862  ScanKeyData key[1];
2863  Relation statrel;
2864  CatalogIndexState indstate = NULL;
2865 
2866  statrel = table_open(StatisticRelationId, RowExclusiveLock);
2867 
2868  /* Now search for stat records */
2869  ScanKeyInit(&key[0],
2870  Anum_pg_statistic_starelid,
2871  BTEqualStrategyNumber, F_OIDEQ,
2872  ObjectIdGetDatum(fromrelid));
2873 
2874  scan = systable_beginscan(statrel, StatisticRelidAttnumInhIndexId,
2875  true, NULL, 1, key);
2876 
2877  while (HeapTupleIsValid((tup = systable_getnext(scan))))
2878  {
2879  Form_pg_statistic statform;
2880 
2881  /* make a modifiable copy */
2882  tup = heap_copytuple(tup);
2883  statform = (Form_pg_statistic) GETSTRUCT(tup);
2884 
2885  /* update the copy of the tuple and insert it */
2886  statform->starelid = torelid;
2887 
2888  /* fetch index information when we know we need it */
2889  if (indstate == NULL)
2890  indstate = CatalogOpenIndexes(statrel);
2891 
2892  CatalogTupleInsertWithInfo(statrel, tup, indstate);
2893 
2894  heap_freetuple(tup);
2895  }
2896 
2897  systable_endscan(scan);
2898 
2899  if (indstate != NULL)
2900  CatalogCloseIndexes(indstate);
2901  table_close(statrel, RowExclusiveLock);
2902 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:256
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:135
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

References BTEqualStrategyNumber, CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTupleInsertWithInfo(), GETSTRUCT, heap_copytuple(), heap_freetuple(), HeapTupleIsValid, sort-test::key, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by index_concurrently_swap().

◆ DeleteAttributeTuples()

void DeleteAttributeTuples ( Oid  relid)

Definition at line 1565 of file heap.c.

1566 {
1567  Relation attrel;
1568  SysScanDesc scan;
1569  ScanKeyData key[1];
1570  HeapTuple atttup;
1571 
1572  /* Grab an appropriate lock on the pg_attribute relation */
1573  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1574 
1575  /* Use the index to scan only attributes of the target relation */
1576  ScanKeyInit(&key[0],
1577  Anum_pg_attribute_attrelid,
1578  BTEqualStrategyNumber, F_OIDEQ,
1579  ObjectIdGetDatum(relid));
1580 
1581  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1582  NULL, 1, key);
1583 
1584  /* Delete all the matching tuples */
1585  while ((atttup = systable_getnext(scan)) != NULL)
1586  CatalogTupleDelete(attrel, &atttup->t_self);
1587 
1588  /* Clean up after the scan */
1589  systable_endscan(scan);
1590  table_close(attrel, RowExclusiveLock);
1591 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
ItemPointerData t_self
Definition: htup.h:65

References BTEqualStrategyNumber, CatalogTupleDelete(), sort-test::key, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by heap_drop_with_catalog(), and index_drop().

◆ DeleteRelationTuple()

void DeleteRelationTuple ( Oid  relid)

Definition at line 1536 of file heap.c.

1537 {
1538  Relation pg_class_desc;
1539  HeapTuple tup;
1540 
1541  /* Grab an appropriate lock on the pg_class relation */
1542  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1543 
1544  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1545  if (!HeapTupleIsValid(tup))
1546  elog(ERROR, "cache lookup failed for relation %u", relid);
1547 
1548  /* delete the relation tuple from pg_class, and finish up */
1549  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1550 
1551  ReleaseSysCache(tup);
1552 
1553  table_close(pg_class_desc, RowExclusiveLock);
1554 }
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:866
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:818
@ RELOID
Definition: syscache.h:89

References CatalogTupleDelete(), elog(), ERROR, HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), RELOID, RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by heap_drop_with_catalog(), and index_drop().

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

Definition at line 1602 of file heap.c.

1603 {
1604  Relation attrel;
1605  SysScanDesc scan;
1606  ScanKeyData key[2];
1607  HeapTuple atttup;
1608 
1609  /* Grab an appropriate lock on the pg_attribute relation */
1610  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1611 
1612  /* Use the index to scan only system attributes of the target relation */
1613  ScanKeyInit(&key[0],
1614  Anum_pg_attribute_attrelid,
1615  BTEqualStrategyNumber, F_OIDEQ,
1616  ObjectIdGetDatum(relid));
1617  ScanKeyInit(&key[1],
1618  Anum_pg_attribute_attnum,
1619  BTLessEqualStrategyNumber, F_INT2LE,
1620  Int16GetDatum(0));
1621 
1622  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1623  NULL, 2, key);
1624 
1625  /* Delete all the matching tuples */
1626  while ((atttup = systable_getnext(scan)) != NULL)
1627  CatalogTupleDelete(attrel, &atttup->t_self);
1628 
1629  /* Clean up after the scan */
1630  systable_endscan(scan);
1631  table_close(attrel, RowExclusiveLock);
1632 }
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30

References BTEqualStrategyNumber, BTLessEqualStrategyNumber, CatalogTupleDelete(), Int16GetDatum(), sort-test::key, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

◆ heap_create()

Relation heap_create ( const char *  relname,
Oid  relnamespace,
Oid  reltablespace,
Oid  relid,
RelFileNumber  relfilenumber,
Oid  accessmtd,
TupleDesc  tupDesc,
char  relkind,
char  relpersistence,
bool  shared_relation,
bool  mapped_relation,
bool  allow_system_table_mods,
TransactionId relfrozenxid,
MultiXactId relminmxid,
bool  create_storage 
)

Definition at line 288 of file heap.c.

303 {
304  Relation rel;
305 
306  /* The caller must have provided an OID for the relation. */
307  Assert(OidIsValid(relid));
308 
309  /*
310  * Don't allow creating relations in pg_catalog directly, even though it
311  * is allowed to move user defined relations there. Semantics with search
312  * paths including pg_catalog are too confusing for now.
313  *
314  * But allow creating indexes on relations in pg_catalog even if
315  * allow_system_table_mods = off, upper layers already guarantee it's on a
316  * user defined relation, not a system one.
317  */
318  if (!allow_system_table_mods &&
319  ((IsCatalogNamespace(relnamespace) && relkind != RELKIND_INDEX) ||
320  IsToastNamespace(relnamespace)) &&
322  ereport(ERROR,
323  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
324  errmsg("permission denied to create \"%s.%s\"",
325  get_namespace_name(relnamespace), relname),
326  errdetail("System catalog modifications are currently disallowed.")));
327 
328  *relfrozenxid = InvalidTransactionId;
329  *relminmxid = InvalidMultiXactId;
330 
331  /*
332  * Force reltablespace to zero if the relation kind does not support
333  * tablespaces. This is mainly just for cleanliness' sake.
334  */
335  if (!RELKIND_HAS_TABLESPACE(relkind))
336  reltablespace = InvalidOid;
337 
338  /* Don't create storage for relkinds without physical storage. */
339  if (!RELKIND_HAS_STORAGE(relkind))
340  create_storage = false;
341  else
342  {
343  /*
344  * If relfilenumber is unspecified by the caller then create storage
345  * with oid same as relid.
346  */
347  if (!RelFileNumberIsValid(relfilenumber))
348  relfilenumber = relid;
349  }
350 
351  /*
352  * Never allow a pg_class entry to explicitly specify the database's
353  * default tablespace in reltablespace; force it to zero instead. This
354  * ensures that if the database is cloned with a different default
355  * tablespace, the pg_class entry will still match where CREATE DATABASE
356  * will put the physically copied relation.
357  *
358  * Yes, this is a bit of a hack.
359  */
360  if (reltablespace == MyDatabaseTableSpace)
361  reltablespace = InvalidOid;
362 
363  /*
364  * build the relcache entry.
365  */
367  relnamespace,
368  tupDesc,
369  relid,
370  accessmtd,
371  relfilenumber,
372  reltablespace,
373  shared_relation,
374  mapped_relation,
375  relpersistence,
376  relkind);
377 
378  /*
379  * Have the storage manager create the relation's disk file, if needed.
380  *
381  * For tables, the AM callback creates both the main and the init fork.
382  * For others, only the main fork is created; the other forks will be
383  * created on demand.
384  */
385  if (create_storage)
386  {
387  if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind))
389  relpersistence,
390  relfrozenxid, relminmxid);
391  else if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
392  RelationCreateStorage(rel->rd_locator, relpersistence, true);
393  else
394  Assert(false);
395  }
396 
397  /*
398  * If a tablespace is specified, removal of that tablespace is normally
399  * protected by the existence of a physical file; but for relations with
400  * no files, add a pg_shdepend entry to account for that.
401  */
402  if (!create_storage && reltablespace != InvalidOid)
403  recordDependencyOnTablespace(RelationRelationId, relid,
404  reltablespace);
405 
406  /* ensure that stats are dropped if transaction aborts */
408 
409  return rel;
410 }
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:202
bool IsCatalogNamespace(Oid namespaceId)
Definition: catalog.c:184
Oid MyDatabaseTableSpace
Definition: globals.c:91
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3324
#define IsNormalProcessingMode()
Definition: miscadmin.h:416
#define InvalidMultiXactId
Definition: multixact.h:24
void recordDependencyOnTablespace(Oid classId, Oid objectId, Oid tablespace)
Definition: pg_shdepend.c:361
void pgstat_create_relation(Relation rel)
Relation RelationBuildLocalRelation(const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid accessmtd, RelFileNumber relfilenumber, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
Definition: relcache.c:3466
#define RelFileNumberIsValid(relnumber)
Definition: relpath.h:27
SMgrRelation RelationCreateStorage(RelFileLocator rlocator, char relpersistence, bool register_delete)
Definition: storage.c:120
RelFileLocator rd_locator
Definition: rel.h:57
static void table_relation_set_new_filelocator(Relation rel, const RelFileLocator *newrlocator, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition: tableam.h:1616
#define InvalidTransactionId
Definition: transam.h:31

References Assert(), ereport, errcode(), errdetail(), errmsg(), ERROR, get_namespace_name(), InvalidMultiXactId, InvalidOid, InvalidTransactionId, IsCatalogNamespace(), IsNormalProcessingMode, IsToastNamespace(), MyDatabaseTableSpace, OidIsValid, pgstat_create_relation(), RelationData::rd_locator, RelationData::rd_rel, recordDependencyOnTablespace(), RelationBuildLocalRelation(), RelationCreateStorage(), RelFileNumberIsValid, relname, and table_relation_set_new_filelocator().

Referenced by heap_create_with_catalog(), and index_create().

◆ heap_create_with_catalog()

Oid heap_create_with_catalog ( const char *  relname,
Oid  relnamespace,
Oid  reltablespace,
Oid  relid,
Oid  reltypeid,
Oid  reloftypeid,
Oid  ownerid,
Oid  accessmtd,
TupleDesc  tupdesc,
List cooked_constraints,
char  relkind,
char  relpersistence,
bool  shared_relation,
bool  mapped_relation,
OnCommitAction  oncommit,
Datum  reloptions,
bool  use_user_acl,
bool  allow_system_table_mods,
bool  is_internal,
Oid  relrewrite,
ObjectAddress typaddress 
)

Definition at line 1091 of file heap.c.

1112 {
1113  Relation pg_class_desc;
1114  Relation new_rel_desc;
1115  Acl *relacl;
1116  Oid existing_relid;
1117  Oid old_type_oid;
1118  Oid new_type_oid;
1119 
1120  /* By default set to InvalidOid unless overridden by binary-upgrade */
1121  RelFileNumber relfilenumber = InvalidRelFileNumber;
1122  TransactionId relfrozenxid;
1123  MultiXactId relminmxid;
1124 
1125  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1126 
1127  /*
1128  * sanity checks
1129  */
1131 
1132  /*
1133  * Validate proposed tupdesc for the desired relkind. If
1134  * allow_system_table_mods is on, allow ANYARRAY to be used; this is a
1135  * hack to allow creating pg_statistic and cloning it during VACUUM FULL.
1136  */
1137  CheckAttributeNamesTypes(tupdesc, relkind,
1138  allow_system_table_mods ? CHKATYPE_ANYARRAY : 0);
1139 
1140  /*
1141  * This would fail later on anyway, if the relation already exists. But
1142  * by catching it here we can emit a nicer error message.
1143  */
1144  existing_relid = get_relname_relid(relname, relnamespace);
1145  if (existing_relid != InvalidOid)
1146  ereport(ERROR,
1147  (errcode(ERRCODE_DUPLICATE_TABLE),
1148  errmsg("relation \"%s\" already exists", relname)));
1149 
1150  /*
1151  * Since we are going to create a rowtype as well, also check for
1152  * collision with an existing type name. If there is one and it's an
1153  * autogenerated array, we can rename it out of the way; otherwise we can
1154  * at least give a good error message.
1155  */
1156  old_type_oid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
1158  ObjectIdGetDatum(relnamespace));
1159  if (OidIsValid(old_type_oid))
1160  {
1161  if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
1162  ereport(ERROR,
1164  errmsg("type \"%s\" already exists", relname),
1165  errhint("A relation has an associated type of the same name, "
1166  "so you must use a name that doesn't conflict "
1167  "with any existing type.")));
1168  }
1169 
1170  /*
1171  * Shared relations must be in pg_global (last-ditch check)
1172  */
1173  if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
1174  elog(ERROR, "shared relations must be placed in pg_global tablespace");
1175 
1176  /*
1177  * Allocate an OID for the relation, unless we were told what to use.
1178  *
1179  * The OID will be the relfilenumber as well, so make sure it doesn't
1180  * collide with either pg_class OIDs or existing physical files.
1181  */
1182  if (!OidIsValid(relid))
1183  {
1184  /* Use binary-upgrade override for pg_class.oid and relfilenumber */
1185  if (IsBinaryUpgrade)
1186  {
1187  /*
1188  * Indexes are not supported here; they use
1189  * binary_upgrade_next_index_pg_class_oid.
1190  */
1191  Assert(relkind != RELKIND_INDEX);
1192  Assert(relkind != RELKIND_PARTITIONED_INDEX);
1193 
1194  if (relkind == RELKIND_TOASTVALUE)
1195  {
1196  /* There might be no TOAST table, so we have to test for it. */
1198  {
1201 
1203  ereport(ERROR,
1204  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1205  errmsg("toast relfilenumber value not set when in binary upgrade mode")));
1206 
1209  }
1210  }
1211  else
1212  {
1214  ereport(ERROR,
1215  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1216  errmsg("pg_class heap OID value not set when in binary upgrade mode")));
1217 
1220 
1221  if (RELKIND_HAS_STORAGE(relkind))
1222  {
1224  ereport(ERROR,
1225  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1226  errmsg("relfilenumber value not set when in binary upgrade mode")));
1227 
1230  }
1231  }
1232  }
1233 
1234  if (!OidIsValid(relid))
1235  relid = GetNewRelFileNumber(reltablespace, pg_class_desc,
1236  relpersistence);
1237  }
1238 
1239  /*
1240  * Determine the relation's initial permissions.
1241  */
1242  if (use_user_acl)
1243  {
1244  switch (relkind)
1245  {
1246  case RELKIND_RELATION:
1247  case RELKIND_VIEW:
1248  case RELKIND_MATVIEW:
1249  case RELKIND_FOREIGN_TABLE:
1250  case RELKIND_PARTITIONED_TABLE:
1251  relacl = get_user_default_acl(OBJECT_TABLE, ownerid,
1252  relnamespace);
1253  break;
1254  case RELKIND_SEQUENCE:
1255  relacl = get_user_default_acl(OBJECT_SEQUENCE, ownerid,
1256  relnamespace);
1257  break;
1258  default:
1259  relacl = NULL;
1260  break;
1261  }
1262  }
1263  else
1264  relacl = NULL;
1265 
1266  /*
1267  * Create the relcache entry (mostly dummy at this point) and the physical
1268  * disk file. (If we fail further down, it's the smgr's responsibility to
1269  * remove the disk file again.)
1270  *
1271  * NB: Note that passing create_storage = true is correct even for binary
1272  * upgrade. The storage we create here will be replaced later, but we
1273  * need to have something on disk in the meanwhile.
1274  */
1275  new_rel_desc = heap_create(relname,
1276  relnamespace,
1277  reltablespace,
1278  relid,
1279  relfilenumber,
1280  accessmtd,
1281  tupdesc,
1282  relkind,
1283  relpersistence,
1284  shared_relation,
1285  mapped_relation,
1286  allow_system_table_mods,
1287  &relfrozenxid,
1288  &relminmxid,
1289  true);
1290 
1291  Assert(relid == RelationGetRelid(new_rel_desc));
1292 
1293  new_rel_desc->rd_rel->relrewrite = relrewrite;
1294 
1295  /*
1296  * Decide whether to create a pg_type entry for the relation's rowtype.
1297  * These types are made except where the use of a relation as such is an
1298  * implementation detail: toast tables, sequences and indexes.
1299  */
1300  if (!(relkind == RELKIND_SEQUENCE ||
1301  relkind == RELKIND_TOASTVALUE ||
1302  relkind == RELKIND_INDEX ||
1303  relkind == RELKIND_PARTITIONED_INDEX))
1304  {
1305  Oid new_array_oid;
1306  ObjectAddress new_type_addr;
1307  char *relarrayname;
1308 
1309  /*
1310  * We'll make an array over the composite type, too. For largely
1311  * historical reasons, the array type's OID is assigned first.
1312  */
1313  new_array_oid = AssignTypeArrayOid();
1314 
1315  /*
1316  * Make the pg_type entry for the composite type. The OID of the
1317  * composite type can be preselected by the caller, but if reltypeid
1318  * is InvalidOid, we'll generate a new OID for it.
1319  *
1320  * NOTE: we could get a unique-index failure here, in case someone
1321  * else is creating the same type name in parallel but hadn't
1322  * committed yet when we checked for a duplicate name above.
1323  */
1324  new_type_addr = AddNewRelationType(relname,
1325  relnamespace,
1326  relid,
1327  relkind,
1328  ownerid,
1329  reltypeid,
1330  new_array_oid);
1331  new_type_oid = new_type_addr.objectId;
1332  if (typaddress)
1333  *typaddress = new_type_addr;
1334 
1335  /* Now create the array type. */
1336  relarrayname = makeArrayTypeName(relname, relnamespace);
1337 
1338  TypeCreate(new_array_oid, /* force the type's OID to this */
1339  relarrayname, /* Array type name */
1340  relnamespace, /* Same namespace as parent */
1341  InvalidOid, /* Not composite, no relationOid */
1342  0, /* relkind, also N/A here */
1343  ownerid, /* owner's ID */
1344  -1, /* Internal size (varlena) */
1345  TYPTYPE_BASE, /* Not composite - typelem is */
1346  TYPCATEGORY_ARRAY, /* type-category (array) */
1347  false, /* array types are never preferred */
1348  DEFAULT_TYPDELIM, /* default array delimiter */
1349  F_ARRAY_IN, /* array input proc */
1350  F_ARRAY_OUT, /* array output proc */
1351  F_ARRAY_RECV, /* array recv (bin) proc */
1352  F_ARRAY_SEND, /* array send (bin) proc */
1353  InvalidOid, /* typmodin procedure - none */
1354  InvalidOid, /* typmodout procedure - none */
1355  F_ARRAY_TYPANALYZE, /* array analyze procedure */
1356  F_ARRAY_SUBSCRIPT_HANDLER, /* array subscript procedure */
1357  new_type_oid, /* array element type - the rowtype */
1358  true, /* yes, this is an array type */
1359  InvalidOid, /* this has no array type */
1360  InvalidOid, /* domain base type - irrelevant */
1361  NULL, /* default value - none */
1362  NULL, /* default binary representation */
1363  false, /* passed by reference */
1364  TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1365  TYPSTORAGE_EXTENDED, /* fully TOASTable */
1366  -1, /* typmod */
1367  0, /* array dimensions for typBaseType */
1368  false, /* Type NOT NULL */
1369  InvalidOid); /* rowtypes never have a collation */
1370 
1371  pfree(relarrayname);
1372  }
1373  else
1374  {
1375  /* Caller should not be expecting a type to be created. */
1376  Assert(reltypeid == InvalidOid);
1377  Assert(typaddress == NULL);
1378 
1379  new_type_oid = InvalidOid;
1380  }
1381 
1382  /*
1383  * now create an entry in pg_class for the relation.
1384  *
1385  * NOTE: we could get a unique-index failure here, in case someone else is
1386  * creating the same relation name in parallel but hadn't committed yet
1387  * when we checked for a duplicate name above.
1388  */
1389  AddNewRelationTuple(pg_class_desc,
1390  new_rel_desc,
1391  relid,
1392  new_type_oid,
1393  reloftypeid,
1394  ownerid,
1395  relkind,
1396  relfrozenxid,
1397  relminmxid,
1398  PointerGetDatum(relacl),
1399  reloptions);
1400 
1401  /*
1402  * now add tuples to pg_attribute for the attributes in our new relation.
1403  */
1404  AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind);
1405 
1406  /*
1407  * Make a dependency link to force the relation to be deleted if its
1408  * namespace is. Also make a dependency link to its owner, as well as
1409  * dependencies for any roles mentioned in the default ACL.
1410  *
1411  * For composite types, these dependencies are tracked for the pg_type
1412  * entry, so we needn't record them here. Likewise, TOAST tables don't
1413  * need a namespace dependency (they live in a pinned namespace) nor an
1414  * owner dependency (they depend indirectly through the parent table), nor
1415  * should they have any ACL entries. The same applies for extension
1416  * dependencies.
1417  *
1418  * Also, skip this in bootstrap mode, since we don't make dependencies
1419  * while bootstrapping.
1420  */
1421  if (relkind != RELKIND_COMPOSITE_TYPE &&
1422  relkind != RELKIND_TOASTVALUE &&
1424  {
1425  ObjectAddress myself,
1426  referenced;
1427  ObjectAddresses *addrs;
1428 
1429  ObjectAddressSet(myself, RelationRelationId, relid);
1430 
1431  recordDependencyOnOwner(RelationRelationId, relid, ownerid);
1432 
1433  recordDependencyOnNewAcl(RelationRelationId, relid, 0, ownerid, relacl);
1434 
1435  recordDependencyOnCurrentExtension(&myself, false);
1436 
1437  addrs = new_object_addresses();
1438 
1439  ObjectAddressSet(referenced, NamespaceRelationId, relnamespace);
1440  add_exact_object_address(&referenced, addrs);
1441 
1442  if (reloftypeid)
1443  {
1444  ObjectAddressSet(referenced, TypeRelationId, reloftypeid);
1445  add_exact_object_address(&referenced, addrs);
1446  }
1447 
1448  /*
1449  * Make a dependency link to force the relation to be deleted if its
1450  * access method is.
1451  *
1452  * No need to add an explicit dependency for the toast table, as the
1453  * main table depends on it.
1454  */
1455  if (RELKIND_HAS_TABLE_AM(relkind) && relkind != RELKIND_TOASTVALUE)
1456  {
1457  ObjectAddressSet(referenced, AccessMethodRelationId, accessmtd);
1458  add_exact_object_address(&referenced, addrs);
1459  }
1460 
1462  free_object_addresses(addrs);
1463  }
1464 
1465  /* Post creation hook for new relation */
1466  InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
1467 
1468  /*
1469  * Store any supplied constraints and defaults.
1470  *
1471  * NB: this may do a CommandCounterIncrement and rebuild the relcache
1472  * entry, so the relation must be valid and self-consistent at this point.
1473  * In particular, there are not yet constraints and defaults anywhere.
1474  */
1475  StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
1476 
1477  /*
1478  * If there's a special on-commit action, remember it
1479  */
1480  if (oncommit != ONCOMMIT_NOOP)
1481  register_on_commit_action(relid, oncommit);
1482 
1483  /*
1484  * ok, the relation has been cataloged, so close our relations and return
1485  * the OID of the newly created relation.
1486  */
1487  table_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
1488  table_close(pg_class_desc, RowExclusiveLock);
1489 
1490  return relid;
1491 }
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition: aclchk.c:4207
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:4131
TransactionId MultiXactId
Definition: c.h:646
uint32 TransactionId
Definition: c.h:636
RelFileNumber GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:502
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2790
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2532
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2581
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2821
bool IsBinaryUpgrade
Definition: globals.c:114
static void StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
Definition: heap.c:2174
static void AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc, char relkind)
Definition: heap.c:804
RelFileNumber binary_upgrade_next_heap_pg_class_relfilenumber
Definition: heap.c:81
static void AddNewRelationTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, Oid reloftype, Oid relowner, char relkind, TransactionId relfrozenxid, TransactionId relminmxid, Datum relacl, Datum reloptions)
Definition: heap.c:955
RelFileNumber binary_upgrade_next_toast_pg_class_relfilenumber
Definition: heap.c:82
static ObjectAddress AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, Oid ownerid, Oid new_row_type, Oid new_array_type)
Definition: heap.c:1013
void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, int flags)
Definition: heap.c:455
Oid binary_upgrade_next_toast_pg_class_oid
Definition: heap.c:80
Oid binary_upgrade_next_heap_pg_class_oid
Definition: heap.c:79
Relation heap_create(const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, RelFileNumber relfilenumber, Oid accessmtd, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods, TransactionId *relfrozenxid, MultiXactId *relminmxid, bool create_storage)
Definition: heap.c:288
#define NoLock
Definition: lockdefs.h:34
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1867
void pfree(void *pointer)
Definition: mcxt.c:1456
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:414
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:175
@ OBJECT_SEQUENCE
Definition: parsenodes.h:2119
@ OBJECT_TABLE
Definition: parsenodes.h:2123
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:192
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:165
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:817
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:882
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
@ ONCOMMIT_NOOP
Definition: primnodes.h:49
Oid RelFileNumber
Definition: relpath.h:25
#define InvalidRelFileNumber
Definition: relpath.h:26
@ TYPENAMENSP
Definition: syscache.h:113
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:202
void register_on_commit_action(Oid relid, OnCommitAction action)
Definition: tablecmds.c:16760
Oid AssignTypeArrayOid(void)
Definition: typecmds.c:2400

References add_exact_object_address(), AddNewAttributeTuples(), AddNewRelationTuple(), AddNewRelationType(), Assert(), AssignTypeArrayOid(), binary_upgrade_next_heap_pg_class_oid, binary_upgrade_next_heap_pg_class_relfilenumber, binary_upgrade_next_toast_pg_class_oid, binary_upgrade_next_toast_pg_class_relfilenumber, CheckAttributeNamesTypes(), CHKATYPE_ANYARRAY, CStringGetDatum(), DEFAULT_TYPDELIM, DEPENDENCY_NORMAL, elog(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg(), ERROR, free_object_addresses(), get_relname_relid(), get_user_default_acl(), GetNewRelFileNumber(), GetSysCacheOid2, heap_create(), InvalidOid, InvalidRelFileNumber, InvokeObjectPostCreateHookArg, IsBinaryUpgrade, IsBootstrapProcessingMode, IsNormalProcessingMode, makeArrayTypeName(), moveArrayTypeName(), new_object_addresses(), NoLock, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum(), OidIsValid, ONCOMMIT_NOOP, pfree(), PointerGetDatum(), RelationData::rd_att, RelationData::rd_rel, record_object_address_dependencies(), recordDependencyOnCurrentExtension(), recordDependencyOnNewAcl(), recordDependencyOnOwner(), register_on_commit_action(), RelationGetRelid, RelFileNumberIsValid, relname, RowExclusiveLock, StoreConstraints(), table_close(), table_open(), TypeCreate(), and TYPENAMENSP.

Referenced by create_toast_table(), DefineRelation(), and make_new_heap().

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

Definition at line 1755 of file heap.c.

1756 {
1757  Relation rel;
1758  HeapTuple tuple;
1759  Oid parentOid = InvalidOid,
1760  defaultPartOid = InvalidOid;
1761 
1762  /*
1763  * To drop a partition safely, we must grab exclusive lock on its parent,
1764  * because another backend might be about to execute a query on the parent
1765  * table. If it relies on previously cached partition descriptor, then it
1766  * could attempt to access the just-dropped relation as its partition. We
1767  * must therefore take a table lock strong enough to prevent all queries
1768  * on the table from proceeding until we commit and send out a
1769  * shared-cache-inval notice that will make them update their partition
1770  * descriptors.
1771  */
1772  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1773  if (!HeapTupleIsValid(tuple))
1774  elog(ERROR, "cache lookup failed for relation %u", relid);
1775  if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
1776  {
1777  /*
1778  * We have to lock the parent if the partition is being detached,
1779  * because it's possible that some query still has a partition
1780  * descriptor that includes this partition.
1781  */
1782  parentOid = get_partition_parent(relid, true);
1784 
1785  /*
1786  * If this is not the default partition, dropping it will change the
1787  * default partition's partition constraint, so we must lock it.
1788  */
1789  defaultPartOid = get_default_partition_oid(parentOid);
1790  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1791  LockRelationOid(defaultPartOid, AccessExclusiveLock);
1792  }
1793 
1794  ReleaseSysCache(tuple);
1795 
1796  /*
1797  * Open and lock the relation.
1798  */
1799  rel = relation_open(relid, AccessExclusiveLock);
1800 
1801  /*
1802  * There can no longer be anyone *else* touching the relation, but we
1803  * might still have open queries or cursors, or pending trigger events, in
1804  * our own session.
1805  */
1806  CheckTableNotInUse(rel, "DROP TABLE");
1807 
1808  /*
1809  * This effectively deletes all rows in the table, and may be done in a
1810  * serializable transaction. In that case we must record a rw-conflict in
1811  * to this transaction from each transaction holding a predicate lock on
1812  * the table.
1813  */
1815 
1816  /*
1817  * Delete pg_foreign_table tuple first.
1818  */
1819  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1820  {
1821  Relation ftrel;
1822  HeapTuple fttuple;
1823 
1824  ftrel = table_open(ForeignTableRelationId, RowExclusiveLock);
1825 
1827  if (!HeapTupleIsValid(fttuple))
1828  elog(ERROR, "cache lookup failed for foreign table %u", relid);
1829 
1830  CatalogTupleDelete(ftrel, &fttuple->t_self);
1831 
1832  ReleaseSysCache(fttuple);
1833  table_close(ftrel, RowExclusiveLock);
1834  }
1835 
1836  /*
1837  * If a partitioned table, delete the pg_partitioned_table tuple.
1838  */
1839  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1841 
1842  /*
1843  * If the relation being dropped is the default partition itself,
1844  * invalidate its entry in pg_partitioned_table.
1845  */
1846  if (relid == defaultPartOid)
1848 
1849  /*
1850  * Schedule unlinking of the relation's physical files at commit.
1851  */
1852  if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
1853  RelationDropStorage(rel);
1854 
1855  /* ensure that stats are dropped if transaction commits */
1856  pgstat_drop_relation(rel);
1857 
1858  /*
1859  * Close relcache entry, but *keep* AccessExclusiveLock on the relation
1860  * until transaction commit. This ensures no one else will try to do
1861  * something with the doomed relation.
1862  */
1863  relation_close(rel, NoLock);
1864 
1865  /*
1866  * Remove any associated relation synchronization states.
1867  */
1869 
1870  /*
1871  * Forget any ON COMMIT action for the rel
1872  */
1873  remove_on_commit_action(relid);
1874 
1875  /*
1876  * Flush the relation from the relcache. We want to do this before
1877  * starting to remove catalog entries, just to be certain that no relcache
1878  * entry rebuild will happen partway through. (That should not really
1879  * matter, since we don't do CommandCounterIncrement here, but let's be
1880  * safe.)
1881  */
1882  RelationForgetRelation(relid);
1883 
1884  /*
1885  * remove inheritance information
1886  */
1888 
1889  /*
1890  * delete statistics
1891  */
1892  RemoveStatistics(relid, 0);
1893 
1894  /*
1895  * delete attribute tuples
1896  */
1897  DeleteAttributeTuples(relid);
1898 
1899  /*
1900  * delete relation tuple
1901  */
1902  DeleteRelationTuple(relid);
1903 
1904  if (OidIsValid(parentOid))
1905  {
1906  /*
1907  * If this is not the default partition, the partition constraint of
1908  * the default partition has changed to include the portion of the key
1909  * space previously covered by the dropped partition.
1910  */
1911  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1912  CacheInvalidateRelcacheByRelid(defaultPartOid);
1913 
1914  /*
1915  * Invalidate the parent's relcache so that the partition is no longer
1916  * included in its partition descriptor.
1917  */
1918  CacheInvalidateRelcacheByRelid(parentOid);
1919  /* keep the lock */
1920  }
1921 }
void DeleteRelationTuple(Oid relid)
Definition: heap.c:1536
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1565
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:2911
static void RelationRemoveInheritance(Oid relid)
Definition: heap.c:1503
void RemovePartitionKeyByRelId(Oid relid)
Definition: heap.c:3438
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1422
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
#define AccessExclusiveLock
Definition: lockdefs.h:43
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:339
Oid get_default_partition_oid(Oid parentId)
Definition: partition.c:314
Oid get_partition_parent(Oid relid, bool even_if_detached)
Definition: partition.c:54
void RemoveSubscriptionRel(Oid subid, Oid relid)
void pgstat_drop_relation(Relation rel)
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4353
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2833
void RelationDropStorage(Relation rel)
Definition: storage.c:205
@ FOREIGNTABLEREL
Definition: syscache.h:65
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:4096
void remove_on_commit_action(Oid relid)
Definition: tablecmds.c:16796

References AccessExclusiveLock, CacheInvalidateRelcacheByRelid(), CatalogTupleDelete(), CheckTableForSerializableConflictIn(), CheckTableNotInUse(), DeleteAttributeTuples(), DeleteRelationTuple(), elog(), ERROR, FOREIGNTABLEREL, get_default_partition_oid(), get_partition_parent(), GETSTRUCT, HeapTupleIsValid, InvalidOid, LockRelationOid(), NoLock, ObjectIdGetDatum(), OidIsValid, pgstat_drop_relation(), RelationData::rd_rel, relation_close(), relation_open(), RelationDropStorage(), RelationForgetRelation(), RelationRemoveInheritance(), ReleaseSysCache(), RELOID, remove_on_commit_action(), RemovePartitionKeyByRelId(), RemoveStatistics(), RemoveSubscriptionRel(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), table_open(), and update_default_partition_oid().

Referenced by doDeletion().

◆ heap_truncate()

void heap_truncate ( List relids)

Definition at line 3006 of file heap.c.

3007 {
3008  List *relations = NIL;
3009  ListCell *cell;
3010 
3011  /* Open relations for processing, and grab exclusive access on each */
3012  foreach(cell, relids)
3013  {
3014  Oid rid = lfirst_oid(cell);
3015  Relation rel;
3016 
3017  rel = table_open(rid, AccessExclusiveLock);
3018  relations = lappend(relations, rel);
3019  }
3020 
3021  /* Don't allow truncate on tables that are referenced by foreign keys */
3022  heap_truncate_check_FKs(relations, true);
3023 
3024  /* OK to do it */
3025  foreach(cell, relations)
3026  {
3027  Relation rel = lfirst(cell);
3028 
3029  /* Truncate the relation */
3030  heap_truncate_one_rel(rel);
3031 
3032  /* Close the relation, but keep exclusive lock on it until commit */
3033  table_close(rel, NoLock);
3034  }
3035 }
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3091
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:3047
#define lfirst_oid(lc)
Definition: pg_list.h:174

References AccessExclusiveLock, heap_truncate_check_FKs(), heap_truncate_one_rel(), lappend(), lfirst, lfirst_oid, NIL, NoLock, table_close(), and table_open().

Referenced by PreCommit_on_commit_actions().

◆ heap_truncate_check_FKs()

void heap_truncate_check_FKs ( List relations,
bool  tempTables 
)

Definition at line 3091 of file heap.c.

3092 {
3093  List *oids = NIL;
3094  List *dependents;
3095  ListCell *cell;
3096 
3097  /*
3098  * Build a list of OIDs of the interesting relations.
3099  *
3100  * If a relation has no triggers, then it can neither have FKs nor be
3101  * referenced by a FK from another table, so we can ignore it. For
3102  * partitioned tables, FKs have no triggers, so we must include them
3103  * anyway.
3104  */
3105  foreach(cell, relations)
3106  {
3107  Relation rel = lfirst(cell);
3108 
3109  if (rel->rd_rel->relhastriggers ||
3110  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3111  oids = lappend_oid(oids, RelationGetRelid(rel));
3112  }
3113 
3114  /*
3115  * Fast path: if no relation has triggers, none has FKs either.
3116  */
3117  if (oids == NIL)
3118  return;
3119 
3120  /*
3121  * Otherwise, must scan pg_constraint. We make one pass with all the
3122  * relations considered; if this finds nothing, then all is well.
3123  */
3124  dependents = heap_truncate_find_FKs(oids);
3125  if (dependents == NIL)
3126  return;
3127 
3128  /*
3129  * Otherwise we repeat the scan once per relation to identify a particular
3130  * pair of relations to complain about. This is pretty slow, but
3131  * performance shouldn't matter much in a failure path. The reason for
3132  * doing things this way is to ensure that the message produced is not
3133  * dependent on chance row locations within pg_constraint.
3134  */
3135  foreach(cell, oids)
3136  {
3137  Oid relid = lfirst_oid(cell);
3138  ListCell *cell2;
3139 
3140  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
3141 
3142  foreach(cell2, dependents)
3143  {
3144  Oid relid2 = lfirst_oid(cell2);
3145 
3146  if (!list_member_oid(oids, relid2))
3147  {
3148  char *relname = get_rel_name(relid);
3149  char *relname2 = get_rel_name(relid2);
3150 
3151  if (tempTables)
3152  ereport(ERROR,
3153  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3154  errmsg("unsupported ON COMMIT and foreign key combination"),
3155  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3156  relname2, relname)));
3157  else
3158  ereport(ERROR,
3159  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3160  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3161  errdetail("Table \"%s\" references \"%s\".",
3162  relname2, relname),
3163  errhint("Truncate table \"%s\" at the same time, "
3164  "or use TRUNCATE ... CASCADE.",
3165  relname2)));
3166  }
3167  }
3168  }
3169 }
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3186
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1910
#define list_make1_oid(x1)
Definition: pg_list.h:242

References ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, get_rel_name(), heap_truncate_find_FKs(), lappend_oid(), lfirst, lfirst_oid, list_make1_oid, list_member_oid(), NIL, RelationData::rd_rel, RelationGetRelid, and relname.

Referenced by ExecuteTruncateGuts(), and heap_truncate().

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

Definition at line 3186 of file heap.c.

3187 {
3188  List *result = NIL;
3189  List *oids;
3190  List *parent_cons;
3191  ListCell *cell;
3192  ScanKeyData key;
3193  Relation fkeyRel;
3194  SysScanDesc fkeyScan;
3195  HeapTuple tuple;
3196  bool restart;
3197 
3198  oids = list_copy(relationIds);
3199 
3200  /*
3201  * Must scan pg_constraint. Right now, it is a seqscan because there is
3202  * no available index on confrelid.
3203  */
3204  fkeyRel = table_open(ConstraintRelationId, AccessShareLock);
3205 
3206 restart:
3207  restart = false;
3208  parent_cons = NIL;
3209 
3210  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3211  NULL, 0, NULL);
3212 
3213  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3214  {
3216 
3217  /* Not a foreign key */
3218  if (con->contype != CONSTRAINT_FOREIGN)
3219  continue;
3220 
3221  /* Not referencing one of our list of tables */
3222  if (!list_member_oid(oids, con->confrelid))
3223  continue;
3224 
3225  /*
3226  * If this constraint has a parent constraint which we have not seen
3227  * yet, keep track of it for the second loop, below. Tracking parent
3228  * constraints allows us to climb up to the top-level constraint and
3229  * look for all possible relations referencing the partitioned table.
3230  */
3231  if (OidIsValid(con->conparentid) &&
3232  !list_member_oid(parent_cons, con->conparentid))
3233  parent_cons = lappend_oid(parent_cons, con->conparentid);
3234 
3235  /*
3236  * Add referencer to result, unless present in input list. (Don't
3237  * worry about dupes: we'll fix that below).
3238  */
3239  if (!list_member_oid(relationIds, con->conrelid))
3240  result = lappend_oid(result, con->conrelid);
3241  }
3242 
3243  systable_endscan(fkeyScan);
3244 
3245  /*
3246  * Process each parent constraint we found to add the list of referenced
3247  * relations by them to the oids list. If we do add any new such
3248  * relations, redo the first loop above. Also, if we see that the parent
3249  * constraint in turn has a parent, add that so that we process all
3250  * relations in a single additional pass.
3251  */
3252  foreach(cell, parent_cons)
3253  {
3254  Oid parent = lfirst_oid(cell);
3255 
3256  ScanKeyInit(&key,
3257  Anum_pg_constraint_oid,
3258  BTEqualStrategyNumber, F_OIDEQ,
3259  ObjectIdGetDatum(parent));
3260 
3261  fkeyScan = systable_beginscan(fkeyRel, ConstraintOidIndexId,
3262  true, NULL, 1, &key);
3263 
3264  tuple = systable_getnext(fkeyScan);
3265  if (HeapTupleIsValid(tuple))
3266  {
3268 
3269  /*
3270  * pg_constraint rows always appear for partitioned hierarchies
3271  * this way: on the each side of the constraint, one row appears
3272  * for each partition that points to the top-most table on the
3273  * other side.
3274  *
3275  * Because of this arrangement, we can correctly catch all
3276  * relevant relations by adding to 'parent_cons' all rows with
3277  * valid conparentid, and to the 'oids' list all rows with a zero
3278  * conparentid. If any oids are added to 'oids', redo the first
3279  * loop above by setting 'restart'.
3280  */
3281  if (OidIsValid(con->conparentid))
3282  parent_cons = list_append_unique_oid(parent_cons,
3283  con->conparentid);
3284  else if (!list_member_oid(oids, con->confrelid))
3285  {
3286  oids = lappend_oid(oids, con->confrelid);
3287  restart = true;
3288  }
3289  }
3290 
3291  systable_endscan(fkeyScan);
3292  }
3293 
3294  list_free(parent_cons);
3295  if (restart)
3296  goto restart;
3297 
3298  table_close(fkeyRel, AccessShareLock);
3299  list_free(oids);
3300 
3301  /* Now sort and de-duplicate the result list */
3302  list_sort(result, list_oid_cmp);
3303  list_deduplicate_oid(result);
3304 
3305  return result;
3306 }
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1673
List * list_copy(const List *oldlist)
Definition: list.c:1572
void list_deduplicate_oid(List *list)
Definition: list.c:1494
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1706
void list_free(List *list)
Definition: list.c:1545
List * list_append_unique_oid(List *list, Oid datum)
Definition: list.c:1379
FormData_pg_constraint * Form_pg_constraint

References AccessShareLock, BTEqualStrategyNumber, GETSTRUCT, HeapTupleIsValid, InvalidOid, sort-test::key, lappend_oid(), lfirst_oid, list_append_unique_oid(), list_copy(), list_deduplicate_oid(), list_free(), list_member_oid(), list_oid_cmp(), list_sort(), NIL, ObjectIdGetDatum(), OidIsValid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ExecuteTruncateGuts(), and heap_truncate_check_FKs().

◆ heap_truncate_one_rel()

void heap_truncate_one_rel ( Relation  rel)

Definition at line 3047 of file heap.c.

3048 {
3049  Oid toastrelid;
3050 
3051  /*
3052  * Truncate the relation. Partitioned tables have no storage, so there is
3053  * nothing to do for them here.
3054  */
3055  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3056  return;
3057 
3058  /* Truncate the underlying relation */
3060 
3061  /* If the relation has indexes, truncate the indexes too */
3063 
3064  /* If there is a toast table, truncate that too */
3065  toastrelid = rel->rd_rel->reltoastrelid;
3066  if (OidIsValid(toastrelid))
3067  {
3068  Relation toastrel = table_open(toastrelid, AccessExclusiveLock);
3069 
3071  RelationTruncateIndexes(toastrel);
3072  /* keep the lock... */
3073  table_close(toastrel, NoLock);
3074  }
3075 }
static void RelationTruncateIndexes(Relation heapRelation)
Definition: heap.c:2958
static void table_relation_nontransactional_truncate(Relation rel)
Definition: tableam.h:1634

References AccessExclusiveLock, NoLock, OidIsValid, RelationData::rd_rel, RelationTruncateIndexes(), table_close(), table_open(), and table_relation_nontransactional_truncate().

Referenced by ExecuteTruncateGuts(), and heap_truncate().

◆ InsertPgAttributeTuples()

void InsertPgAttributeTuples ( Relation  pg_attribute_rel,
TupleDesc  tupdesc,
Oid  new_rel_oid,
Datum attoptions,
CatalogIndexState  indstate 
)

Definition at line 697 of file heap.c.

702 {
703  TupleTableSlot **slot;
704  TupleDesc td;
705  int nslots;
706  int natts = 0;
707  int slotCount = 0;
708  bool close_index = false;
709 
710  td = RelationGetDescr(pg_attribute_rel);
711 
712  /* Initialize the number of slots to use */
713  nslots = Min(tupdesc->natts,
715  slot = palloc(sizeof(TupleTableSlot *) * nslots);
716  for (int i = 0; i < nslots; i++)
718 
719  while (natts < tupdesc->natts)
720  {
721  Form_pg_attribute attrs = TupleDescAttr(tupdesc, natts);
722 
723  ExecClearTuple(slot[slotCount]);
724 
725  memset(slot[slotCount]->tts_isnull, false,
726  slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool));
727 
728  if (new_rel_oid != InvalidOid)
729  slot[slotCount]->tts_values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_rel_oid);
730  else
731  slot[slotCount]->tts_values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(attrs->attrelid);
732 
733  slot[slotCount]->tts_values[Anum_pg_attribute_attname - 1] = NameGetDatum(&attrs->attname);
734  slot[slotCount]->tts_values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(attrs->atttypid);
735  slot[slotCount]->tts_values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(attrs->attlen);
736  slot[slotCount]->tts_values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(attrs->attnum);
737  slot[slotCount]->tts_values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
738  slot[slotCount]->tts_values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(attrs->atttypmod);
739  slot[slotCount]->tts_values[Anum_pg_attribute_attndims - 1] = Int16GetDatum(attrs->attndims);
740  slot[slotCount]->tts_values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(attrs->attbyval);
741  slot[slotCount]->tts_values[Anum_pg_attribute_attalign - 1] = CharGetDatum(attrs->attalign);
742  slot[slotCount]->tts_values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(attrs->attstorage);
743  slot[slotCount]->tts_values[Anum_pg_attribute_attcompression - 1] = CharGetDatum(attrs->attcompression);
744  slot[slotCount]->tts_values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(attrs->attnotnull);
745  slot[slotCount]->tts_values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(attrs->atthasdef);
746  slot[slotCount]->tts_values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(attrs->atthasmissing);
747  slot[slotCount]->tts_values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(attrs->attidentity);
748  slot[slotCount]->tts_values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(attrs->attgenerated);
749  slot[slotCount]->tts_values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(attrs->attisdropped);
750  slot[slotCount]->tts_values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(attrs->attislocal);
751  slot[slotCount]->tts_values[Anum_pg_attribute_attinhcount - 1] = Int16GetDatum(attrs->attinhcount);
752  slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = Int16GetDatum(attrs->attstattarget);
753  slot[slotCount]->tts_values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(attrs->attcollation);
754  if (attoptions && attoptions[natts] != (Datum) 0)
755  slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attoptions[natts];
756  else
757  slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = true;
758 
759  /* start out with empty permissions and empty options */
760  slot[slotCount]->tts_isnull[Anum_pg_attribute_attacl - 1] = true;
761  slot[slotCount]->tts_isnull[Anum_pg_attribute_attfdwoptions - 1] = true;
762  slot[slotCount]->tts_isnull[Anum_pg_attribute_attmissingval - 1] = true;
763 
764  ExecStoreVirtualTuple(slot[slotCount]);
765  slotCount++;
766 
767  /*
768  * If slots are full or the end of processing has been reached, insert
769  * a batch of tuples.
770  */
771  if (slotCount == nslots || natts == tupdesc->natts - 1)
772  {
773  /* fetch index info only when we know we need it */
774  if (!indstate)
775  {
776  indstate = CatalogOpenIndexes(pg_attribute_rel);
777  close_index = true;
778  }
779 
780  /* insert the new tuples and update the indexes */
781  CatalogTuplesMultiInsertWithInfo(pg_attribute_rel, slot, slotCount,
782  indstate);
783  slotCount = 0;
784  }
785 
786  natts++;
787  }
788 
789  if (close_index)
790  CatalogCloseIndexes(indstate);
791  for (int i = 0; i < nslots; i++)
793  pfree(slot);
794 }
#define Min(x, y)
Definition: c.h:988
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1553
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1255
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:84
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1239
void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate)
Definition: indexing.c:273
#define MAX_CATALOG_MULTI_INSERT_BYTES
Definition: indexing.h:33
uintptr_t Datum
Definition: postgres.h:64
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:373
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static Datum CharGetDatum(char X)
Definition: postgres.h:122
bool * tts_isnull
Definition: tuptable.h:128
Datum * tts_values
Definition: tuptable.h:126
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:433

References BoolGetDatum(), CatalogCloseIndexes(), CatalogOpenIndexes(), CatalogTuplesMultiInsertWithInfo(), CharGetDatum(), ExecClearTuple(), ExecDropSingleTupleTableSlot(), ExecStoreVirtualTuple(), FormData_pg_attribute, i, Int16GetDatum(), Int32GetDatum(), InvalidOid, MakeSingleTupleTableSlot(), MAX_CATALOG_MULTI_INSERT_BYTES, Min, NameGetDatum(), TupleDescData::natts, ObjectIdGetDatum(), palloc(), pfree(), RelationGetDescr, TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, TTSOpsHeapTuple, and TupleDescAttr.

Referenced by AddNewAttributeTuples(), AppendAttributeTuples(), and ATExecAddColumn().

◆ InsertPgClassTuple()

void InsertPgClassTuple ( Relation  pg_class_desc,
Relation  new_rel_desc,
Oid  new_rel_oid,
Datum  relacl,
Datum  reloptions 
)

Definition at line 882 of file heap.c.

887 {
888  Form_pg_class rd_rel = new_rel_desc->rd_rel;
889  Datum values[Natts_pg_class];
890  bool nulls[Natts_pg_class];
891  HeapTuple tup;
892 
893  /* This is a tad tedious, but way cleaner than what we used to do... */
894  memset(values, 0, sizeof(values));
895  memset(nulls, false, sizeof(nulls));
896 
897  values[Anum_pg_class_oid - 1] = ObjectIdGetDatum(new_rel_oid);
898  values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
899  values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
900  values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
901  values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
902  values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
903  values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
904  values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
905  values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
906  values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
907  values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
908  values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
909  values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
910  values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
911  values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
912  values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
913  values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
914  values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
915  values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
916  values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
917  values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
918  values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
919  values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
920  values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
921  values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
922  values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
923  values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
924  values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite);
925  values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
926  values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
927  if (relacl != (Datum) 0)
928  values[Anum_pg_class_relacl - 1] = relacl;
929  else
930  nulls[Anum_pg_class_relacl - 1] = true;
931  if (reloptions != (Datum) 0)
932  values[Anum_pg_class_reloptions - 1] = reloptions;
933  else
934  nulls[Anum_pg_class_reloptions - 1] = true;
935 
936  /* relpartbound is set by updating this tuple, if necessary */
937  nulls[Anum_pg_class_relpartbound - 1] = true;
938 
939  tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
940 
941  /* finally insert the new tuple, update the indexes, and clean up */
942  CatalogTupleInsert(pg_class_desc, tup);
943 
944  heap_freetuple(tup);
945 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
static Datum Float4GetDatum(float4 X)
Definition: postgres.h:475
static Datum TransactionIdGetDatum(TransactionId X)
Definition: postgres.h:272
static Datum MultiXactIdGetDatum(MultiXactId X)
Definition: postgres.h:282

References BoolGetDatum(), CatalogTupleInsert(), CharGetDatum(), Float4GetDatum(), heap_form_tuple(), heap_freetuple(), Int16GetDatum(), Int32GetDatum(), MultiXactIdGetDatum(), NameGetDatum(), ObjectIdGetDatum(), RelationData::rd_rel, RelationGetDescr, TransactionIdGetDatum(), and values.

Referenced by AddNewRelationTuple(), and index_create().

◆ MergeWithExistingConstraint()

static bool MergeWithExistingConstraint ( Relation  rel,
const char *  ccname,
Node expr,
bool  allow_merge,
bool  is_local,
bool  is_initially_valid,
bool  is_no_inherit 
)
static

Definition at line 2496 of file heap.c.

2500 {
2501  bool found;
2502  Relation conDesc;
2503  SysScanDesc conscan;
2504  ScanKeyData skey[3];
2505  HeapTuple tup;
2506 
2507  /* Search for a pg_constraint entry with same name and relation */
2508  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
2509 
2510  found = false;
2511 
2512  ScanKeyInit(&skey[0],
2513  Anum_pg_constraint_conrelid,
2514  BTEqualStrategyNumber, F_OIDEQ,
2516  ScanKeyInit(&skey[1],
2517  Anum_pg_constraint_contypid,
2518  BTEqualStrategyNumber, F_OIDEQ,
2520  ScanKeyInit(&skey[2],
2521  Anum_pg_constraint_conname,
2522  BTEqualStrategyNumber, F_NAMEEQ,
2523  CStringGetDatum(ccname));
2524 
2525  conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId, true,
2526  NULL, 3, skey);
2527 
2528  /* There can be at most one matching row */
2529  if (HeapTupleIsValid(tup = systable_getnext(conscan)))
2530  {
2532 
2533  /* Found it. Conflicts if not identical check constraint */
2534  if (con->contype == CONSTRAINT_CHECK)
2535  {
2536  Datum val;
2537  bool isnull;
2538 
2539  val = fastgetattr(tup,
2540  Anum_pg_constraint_conbin,
2541  conDesc->rd_att, &isnull);
2542  if (isnull)
2543  elog(ERROR, "null conbin for rel %s",
2546  found = true;
2547  }
2548 
2549  /*
2550  * If the existing constraint is purely inherited (no local
2551  * definition) then interpret addition of a local constraint as a
2552  * legal merge. This allows ALTER ADD CONSTRAINT on parent and child
2553  * tables to be given in either order with same end state. However if
2554  * the relation is a partition, all inherited constraints are always
2555  * non-local, including those that were merged.
2556  */
2557  if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
2558  allow_merge = true;
2559 
2560  if (!found || !allow_merge)
2561  ereport(ERROR,
2563  errmsg("constraint \"%s\" for relation \"%s\" already exists",
2564  ccname, RelationGetRelationName(rel))));
2565 
2566  /* If the child constraint is "no inherit" then cannot merge */
2567  if (con->connoinherit)
2568  ereport(ERROR,
2569  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2570  errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
2571  ccname, RelationGetRelationName(rel))));
2572 
2573  /*
2574  * Must not change an existing inherited constraint to "no inherit"
2575  * status. That's because inherited constraints should be able to
2576  * propagate to lower-level children.
2577  */
2578  if (con->coninhcount > 0 && is_no_inherit)
2579  ereport(ERROR,
2580  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2581  errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
2582  ccname, RelationGetRelationName(rel))));
2583 
2584  /*
2585  * If the child constraint is "not valid" then cannot merge with a
2586  * valid parent constraint.
2587  */
2588  if (is_initially_valid && !con->convalidated)
2589  ereport(ERROR,
2590  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2591  errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
2592  ccname, RelationGetRelationName(rel))));
2593 
2594  /* OK to update the tuple */
2595  ereport(NOTICE,
2596  (errmsg("merging constraint \"%s\" with inherited definition",
2597  ccname)));
2598 
2599  tup = heap_copytuple(tup);
2600  con = (Form_pg_constraint) GETSTRUCT(tup);
2601 
2602  /*
2603  * In case of partitions, an inherited constraint must be inherited
2604  * only once since it cannot have multiple parents and it is never
2605  * considered local.
2606  */
2607  if (rel->rd_rel->relispartition)
2608  {
2609  con->coninhcount = 1;
2610  con->conislocal = false;
2611  }
2612  else
2613  {
2614  if (is_local)
2615  con->conislocal = true;
2616  else
2617  con->coninhcount++;
2618 
2619  if (con->coninhcount < 0)
2620  ereport(ERROR,
2621  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2622  errmsg("too many inheritance parents"));
2623  }
2624 
2625  if (is_no_inherit)
2626  {
2627  Assert(is_local);
2628  con->connoinherit = true;
2629  }
2630 
2631  CatalogTupleUpdate(conDesc, &tup->t_self, tup);
2632  }
2633 
2634  systable_endscan(conscan);
2635  table_close(conDesc, RowExclusiveLock);
2636 
2637  return found;
2638 }
#define TextDatumGetCString(d)
Definition: builtins.h:95
#define NOTICE
Definition: elog.h:35
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:749
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
long val
Definition: informix.c:664

References Assert(), BTEqualStrategyNumber, CatalogTupleUpdate(), CStringGetDatum(), elog(), equal(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, fastgetattr(), GETSTRUCT, heap_copytuple(), HeapTupleIsValid, InvalidOid, NOTICE, ObjectIdGetDatum(), RelationData::rd_att, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, RowExclusiveLock, ScanKeyInit(), stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), TextDatumGetCString, and val.

Referenced by AddRelationNewConstraints().

◆ RelationClearMissing()

void RelationClearMissing ( Relation  rel)

Definition at line 1935 of file heap.c.

1936 {
1937  Relation attr_rel;
1938  Oid relid = RelationGetRelid(rel);
1939  int natts = RelationGetNumberOfAttributes(rel);
1940  int attnum;
1941  Datum repl_val[Natts_pg_attribute];
1942  bool repl_null[Natts_pg_attribute];
1943  bool repl_repl[Natts_pg_attribute];
1944  Form_pg_attribute attrtuple;
1945  HeapTuple tuple,
1946  newtuple;
1947 
1948  memset(repl_val, 0, sizeof(repl_val));
1949  memset(repl_null, false, sizeof(repl_null));
1950  memset(repl_repl, false, sizeof(repl_repl));
1951 
1952  repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
1953  repl_null[Anum_pg_attribute_attmissingval - 1] = true;
1954 
1955  repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
1956  repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
1957 
1958 
1959  /* Get a lock on pg_attribute */
1960  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1961 
1962  /* process each non-system attribute, including any dropped columns */
1963  for (attnum = 1; attnum <= natts; attnum++)
1964  {
1965  tuple = SearchSysCache2(ATTNUM,
1966  ObjectIdGetDatum(relid),
1968  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1969  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1970  attnum, relid);
1971 
1972  attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
1973 
1974  /* ignore any where atthasmissing is not true */
1975  if (attrtuple->atthasmissing)
1976  {
1977  newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
1978  repl_val, repl_null, repl_repl);
1979 
1980  CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
1981 
1982  heap_freetuple(newtuple);
1983  }
1984 
1985  ReleaseSysCache(tuple);
1986  }
1987 
1988  /*
1989  * Our update of the pg_attribute rows will force a relcache rebuild, so
1990  * there's nothing else to do here.
1991  */
1992  table_close(attr_rel, RowExclusiveLock);
1993 }
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:510
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:829
@ ATTNUM
Definition: syscache.h:41

References attnum, ATTNUM, BoolGetDatum(), CatalogTupleUpdate(), elog(), ERROR, GETSTRUCT, heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum(), ObjectIdGetDatum(), RelationGetDescr, RelationGetNumberOfAttributes, RelationGetRelid, ReleaseSysCache(), RowExclusiveLock, SearchSysCache2(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by ATExecAlterColumnType(), and finish_heap_swap().

◆ RelationRemoveInheritance()

static void RelationRemoveInheritance ( Oid  relid)
static

Definition at line 1503 of file heap.c.

1504 {
1505  Relation catalogRelation;
1506  SysScanDesc scan;
1507  ScanKeyData key;
1508  HeapTuple tuple;
1509 
1510  catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
1511 
1512  ScanKeyInit(&key,
1513  Anum_pg_inherits_inhrelid,
1514  BTEqualStrategyNumber, F_OIDEQ,
1515  ObjectIdGetDatum(relid));
1516 
1517  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
1518  NULL, 1, &key);
1519 
1520  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1521  CatalogTupleDelete(catalogRelation, &tuple->t_self);
1522 
1523  systable_endscan(scan);
1524  table_close(catalogRelation, RowExclusiveLock);
1525 }

References BTEqualStrategyNumber, CatalogTupleDelete(), HeapTupleIsValid, sort-test::key, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by heap_drop_with_catalog().

◆ RelationTruncateIndexes()

static void RelationTruncateIndexes ( Relation  heapRelation)
static

Definition at line 2958 of file heap.c.

2959 {
2960  ListCell *indlist;
2961 
2962  /* Ask the relcache to produce a list of the indexes of the rel */
2963  foreach(indlist, RelationGetIndexList(heapRelation))
2964  {
2965  Oid indexId = lfirst_oid(indlist);
2966  Relation currentIndex;
2967  IndexInfo *indexInfo;
2968 
2969  /* Open the index relation; use exclusive lock, just to be sure */
2970  currentIndex = index_open(indexId, AccessExclusiveLock);
2971 
2972  /*
2973  * Fetch info needed for index_build. Since we know there are no
2974  * tuples that actually need indexing, we can use a dummy IndexInfo.
2975  * This is slightly cheaper to build, but the real point is to avoid
2976  * possibly running user-defined code in index expressions or
2977  * predicates. We might be getting invoked during ON COMMIT
2978  * processing, and we don't want to run any such code then.
2979  */
2980  indexInfo = BuildDummyIndexInfo(currentIndex);
2981 
2982  /*
2983  * Now truncate the actual file (and discard buffers).
2984  */
2985  RelationTruncate(currentIndex, 0);
2986 
2987  /* Initialize the index and rebuild */
2988  /* Note: we do not need to re-establish pkey setting */
2989  index_build(heapRelation, currentIndex, indexInfo, true, false);
2990 
2991  /* We're done with this index */
2992  index_close(currentIndex, NoLock);
2993  }
2994 }
IndexInfo * BuildDummyIndexInfo(Relation index)
Definition: index.c:2491
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isreindex, bool parallel)
Definition: index.c:2957
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4739
void RelationTruncate(Relation rel, BlockNumber nblocks)
Definition: storage.c:287

References AccessExclusiveLock, BuildDummyIndexInfo(), index_build(), index_close(), index_open(), lfirst_oid, NoLock, RelationGetIndexList(), and RelationTruncate().

Referenced by heap_truncate_one_rel().

◆ RemoveAttributeById()

void RemoveAttributeById ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 1643 of file heap.c.

1644 {
1645  Relation rel;
1646  Relation attr_rel;
1647  HeapTuple tuple;
1648  Form_pg_attribute attStruct;
1649  char newattname[NAMEDATALEN];
1650 
1651  /*
1652  * Grab an exclusive lock on the target table, which we will NOT release
1653  * until end of transaction. (In the simple case where we are directly
1654  * dropping this column, ATExecDropColumn already did this ... but when
1655  * cascading from a drop of some other object, we may not have any lock.)
1656  */
1657  rel = relation_open(relid, AccessExclusiveLock);
1658 
1659  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1660 
1661  tuple = SearchSysCacheCopy2(ATTNUM,
1662  ObjectIdGetDatum(relid),
1664  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1665  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1666  attnum, relid);
1667  attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
1668 
1669  if (attnum < 0)
1670  {
1671  /* System attribute (probably OID) ... just delete the row */
1672 
1673  CatalogTupleDelete(attr_rel, &tuple->t_self);
1674  }
1675  else
1676  {
1677  /* Dropping user attributes is lots harder */
1678 
1679  /* Mark the attribute as dropped */
1680  attStruct->attisdropped = true;
1681 
1682  /*
1683  * Set the type OID to invalid. A dropped attribute's type link
1684  * cannot be relied on (once the attribute is dropped, the type might
1685  * be too). Fortunately we do not need the type row --- the only
1686  * really essential information is the type's typlen and typalign,
1687  * which are preserved in the attribute's attlen and attalign. We set
1688  * atttypid to zero here as a means of catching code that incorrectly
1689  * expects it to be valid.
1690  */
1691  attStruct->atttypid = InvalidOid;
1692 
1693  /* Remove any NOT NULL constraint the column may have */
1694  attStruct->attnotnull = false;
1695 
1696  /* We don't want to keep stats for it anymore */
1697  attStruct->attstattarget = 0;
1698 
1699  /* Unset this so no one tries to look up the generation expression */
1700  attStruct->attgenerated = '\0';
1701 
1702  /*
1703  * Change the column name to something that isn't likely to conflict
1704  */
1705  snprintf(newattname, sizeof(newattname),
1706  "........pg.dropped.%d........", attnum);
1707  namestrcpy(&(attStruct->attname), newattname);
1708 
1709  /* clear the missing value if any */
1710  if (attStruct->atthasmissing)
1711  {
1712  Datum valuesAtt[Natts_pg_attribute] = {0};
1713  bool nullsAtt[Natts_pg_attribute] = {0};
1714  bool replacesAtt[Natts_pg_attribute] = {0};
1715 
1716  /* update the tuple - set atthasmissing and attmissingval */
1717  valuesAtt[Anum_pg_attribute_atthasmissing - 1] =
1718  BoolGetDatum(false);
1719  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
1720  valuesAtt[Anum_pg_attribute_attmissingval - 1] = (Datum) 0;
1721  nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
1722  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
1723 
1724  tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
1725  valuesAtt, nullsAtt, replacesAtt);
1726  }
1727 
1728  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1729  }
1730 
1731  /*
1732  * Because updating the pg_attribute row will trigger a relcache flush for
1733  * the target relation, we need not do anything else to notify other
1734  * backends of the change.
1735  */
1736 
1737  table_close(attr_rel, RowExclusiveLock);
1738 
1739  if (attnum > 0)
1740  RemoveStatistics(relid, attnum);
1741 
1742  relation_close(rel, NoLock);
1743 }
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define NAMEDATALEN
#define snprintf
Definition: port.h:238
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:184

References AccessExclusiveLock, attnum, ATTNUM, BoolGetDatum(), CatalogTupleDelete(), CatalogTupleUpdate(), elog(), ERROR, GETSTRUCT, heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum(), InvalidOid, NAMEDATALEN, namestrcpy(), NoLock, ObjectIdGetDatum(), relation_close(), relation_open(), RelationGetDescr, RemoveStatistics(), RowExclusiveLock, SearchSysCacheCopy2, snprintf, HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

Definition at line 3438 of file heap.c.

3439 {
3440  Relation rel;
3441  HeapTuple tuple;
3442 
3443  rel = table_open(PartitionedRelationId, RowExclusiveLock);
3444 
3445  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3446  if (!HeapTupleIsValid(tuple))
3447  elog(ERROR, "cache lookup failed for partition key of relation %u",
3448  relid);
3449 
3450  CatalogTupleDelete(rel, &tuple->t_self);
3451 
3452  ReleaseSysCache(tuple);
3454 }
@ PARTRELID
Definition: syscache.h:77

References CatalogTupleDelete(), elog(), ERROR, HeapTupleIsValid, ObjectIdGetDatum(), PARTRELID, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by heap_drop_with_catalog().

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 2911 of file heap.c.

2912 {
2913  Relation pgstatistic;
2914  SysScanDesc scan;
2915  ScanKeyData key[2];
2916  int nkeys;
2917  HeapTuple tuple;
2918 
2919  pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
2920 
2921  ScanKeyInit(&key[0],
2922  Anum_pg_statistic_starelid,
2923  BTEqualStrategyNumber, F_OIDEQ,
2924  ObjectIdGetDatum(relid));
2925 
2926  if (attnum == 0)
2927  nkeys = 1;
2928  else
2929  {
2930  ScanKeyInit(&key[1],
2931  Anum_pg_statistic_staattnum,
2932  BTEqualStrategyNumber, F_INT2EQ,
2934  nkeys = 2;
2935  }
2936 
2937  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
2938  NULL, nkeys, key);
2939 
2940  /* we must loop even when attnum != 0, in case of inherited stats */
2941  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
2942  CatalogTupleDelete(pgstatistic, &tuple->t_self);
2943 
2944  systable_endscan(scan);
2945 
2946  table_close(pgstatistic, RowExclusiveLock);
2947 }

References attnum, BTEqualStrategyNumber, CatalogTupleDelete(), HeapTupleIsValid, Int16GetDatum(), sort-test::key, ObjectIdGetDatum(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by ATExecAlterColumnType(), heap_drop_with_catalog(), index_drop(), and RemoveAttributeById().

◆ SetAttrMissing()

void SetAttrMissing ( Oid  relid,
char *  attname,
char *  value 
)

Definition at line 2003 of file heap.c.

2004 {
2005  Datum valuesAtt[Natts_pg_attribute] = {0};
2006  bool nullsAtt[Natts_pg_attribute] = {0};
2007  bool replacesAtt[Natts_pg_attribute] = {0};
2008  Datum missingval;
2009  Form_pg_attribute attStruct;
2010  Relation attrrel,
2011  tablerel;
2012  HeapTuple atttup,
2013  newtup;
2014 
2015  /* lock the table the attribute belongs to */
2016  tablerel = table_open(relid, AccessExclusiveLock);
2017 
2018  /* Don't do anything unless it's a plain table */
2019  if (tablerel->rd_rel->relkind != RELKIND_RELATION)
2020  {
2021  table_close(tablerel, AccessExclusiveLock);
2022  return;
2023  }
2024 
2025  /* Lock the attribute row and get the data */
2026  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2027  atttup = SearchSysCacheAttName(relid, attname);
2028  if (!HeapTupleIsValid(atttup))
2029  elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2030  attname, relid);
2031  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2032 
2033  /* get an array value from the value string */
2034  missingval = OidFunctionCall3(F_ARRAY_IN,
2036  ObjectIdGetDatum(attStruct->atttypid),
2037  Int32GetDatum(attStruct->atttypmod));
2038 
2039  /* update the tuple - set atthasmissing and attmissingval */
2040  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
2041  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2042  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2043  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2044 
2045  newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2046  valuesAtt, nullsAtt, replacesAtt);
2047  CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
2048 
2049  /* clean up */
2050  ReleaseSysCache(atttup);
2051  table_close(attrrel, RowExclusiveLock);
2052  table_close(tablerel, AccessExclusiveLock);
2053 }
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition: fmgr.h:684
static struct @147 value
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:959

References AccessExclusiveLock, attname, BoolGetDatum(), CatalogTupleUpdate(), CStringGetDatum(), elog(), ERROR, GETSTRUCT, heap_modify_tuple(), HeapTupleIsValid, Int32GetDatum(), ObjectIdGetDatum(), OidFunctionCall3, RelationData::rd_rel, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCacheAttName(), HeapTupleData::t_self, table_close(), table_open(), and value.

Referenced by binary_upgrade_set_missing_value().

◆ SetRelationNumChecks()

static void SetRelationNumChecks ( Relation  rel,
int  numchecks 
)
static

Definition at line 2651 of file heap.c.

2652 {
2653  Relation relrel;
2654  HeapTuple reltup;
2655  Form_pg_class relStruct;
2656 
2657  relrel = table_open(RelationRelationId, RowExclusiveLock);
2658  reltup = SearchSysCacheCopy1(RELOID,
2660  if (!HeapTupleIsValid(reltup))
2661  elog(ERROR, "cache lookup failed for relation %u",
2662  RelationGetRelid(rel));
2663  relStruct = (Form_pg_class) GETSTRUCT(reltup);
2664 
2665  if (relStruct->relchecks != numchecks)
2666  {
2667  relStruct->relchecks = numchecks;
2668 
2669  CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
2670  }
2671  else
2672  {
2673  /* Skip the disk update, but force relcache inval anyway */
2675  }
2676 
2677  heap_freetuple(reltup);
2678  table_close(relrel, RowExclusiveLock);
2679 }
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1363
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:182

References CacheInvalidateRelcache(), CatalogTupleUpdate(), elog(), ERROR, GETSTRUCT, heap_freetuple(), HeapTupleIsValid, ObjectIdGetDatum(), RelationGetRelid, RELOID, RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), and table_open().

Referenced by AddRelationNewConstraints(), and StoreConstraints().

◆ StoreConstraints()

static void StoreConstraints ( Relation  rel,
List cooked_constraints,
bool  is_internal 
)
static

Definition at line 2174 of file heap.c.

2175 {
2176  int numchecks = 0;
2177  ListCell *lc;
2178 
2179  if (cooked_constraints == NIL)
2180  return; /* nothing to do */
2181 
2182  /*
2183  * Deparsing of constraint expressions will fail unless the just-created
2184  * pg_attribute tuples for this relation are made visible. So, bump the
2185  * command counter. CAUTION: this will cause a relcache entry rebuild.
2186  */
2188 
2189  foreach(lc, cooked_constraints)
2190  {
2191  CookedConstraint *con = (CookedConstraint *) lfirst(lc);
2192 
2193  switch (con->contype)
2194  {
2195  case CONSTR_DEFAULT:
2196  con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
2197  is_internal, false);
2198  break;
2199  case CONSTR_CHECK:
2200  con->conoid =
2201  StoreRelCheck(rel, con->name, con->expr,
2202  !con->skip_validation, con->is_local,
2203  con->inhcount, con->is_no_inherit,
2204  is_internal);
2205  numchecks++;
2206  break;
2207  default:
2208  elog(ERROR, "unrecognized constraint type: %d",
2209  (int) con->contype);
2210  }
2211  }
2212 
2213  if (numchecks > 0)
2214  SetRelationNumChecks(rel, numchecks);
2215 }
void CommandCounterIncrement(void)
Definition: xact.c:1078

References CookedConstraint::attnum, CommandCounterIncrement(), CookedConstraint::conoid, CONSTR_CHECK, CONSTR_DEFAULT, CookedConstraint::contype, elog(), ERROR, CookedConstraint::expr, CookedConstraint::inhcount, CookedConstraint::is_local, CookedConstraint::is_no_inherit, lfirst, CookedConstraint::name, NIL, SetRelationNumChecks(), CookedConstraint::skip_validation, StoreAttrDefault(), and StoreRelCheck().

Referenced by heap_create_with_catalog().

◆ StorePartitionBound()

void StorePartitionBound ( Relation  rel,
Relation  parent,
PartitionBoundSpec bound 
)

Definition at line 3469 of file heap.c.

3470 {
3471  Relation classRel;
3472  HeapTuple tuple,
3473  newtuple;
3474  Datum new_val[Natts_pg_class];
3475  bool new_null[Natts_pg_class],
3476  new_repl[Natts_pg_class];
3477  Oid defaultPartOid;
3478 
3479  /* Update pg_class tuple */
3480  classRel = table_open(RelationRelationId, RowExclusiveLock);
3481  tuple = SearchSysCacheCopy1(RELOID,
3483  if (!HeapTupleIsValid(tuple))
3484  elog(ERROR, "cache lookup failed for relation %u",
3485  RelationGetRelid(rel));
3486 
3487 #ifdef USE_ASSERT_CHECKING
3488  {
3489  Form_pg_class classForm;
3490  bool isnull;
3491 
3492  classForm = (Form_pg_class) GETSTRUCT(tuple);
3493  Assert(!classForm->relispartition);
3494  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3495  &isnull);
3496  Assert(isnull);
3497  }
3498 #endif
3499 
3500  /* Fill in relpartbound value */
3501  memset(new_val, 0, sizeof(new_val));
3502  memset(new_null, false, sizeof(new_null));
3503  memset(new_repl, false, sizeof(new_repl));
3504  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3505  new_null[Anum_pg_class_relpartbound - 1] = false;
3506  new_repl[Anum_pg_class_relpartbound - 1] = true;
3507  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3508  new_val, new_null, new_repl);
3509  /* Also set the flag */
3510  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3511  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3512  heap_freetuple(newtuple);
3513  table_close(classRel, RowExclusiveLock);
3514 
3515  /*
3516  * If we're storing bounds for the default partition, update
3517  * pg_partitioned_table too.
3518  */
3519  if (bound->is_default)
3521  RelationGetRelid(rel));
3522 
3523  /* Make these updates visible */
3525 
3526  /*
3527  * The partition constraint for the default partition depends on the
3528  * partition bounds of every other partition, so we must invalidate the
3529  * relcache entry for that partition every time a partition is added or
3530  * removed.
3531  */
3532  defaultPartOid =
3534  if (OidIsValid(defaultPartOid))
3535  CacheInvalidateRelcacheByRelid(defaultPartOid);
3536 
3537  CacheInvalidateRelcache(parent);
3538 }
#define CStringGetTextDatum(s)
Definition: builtins.h:94
char * nodeToString(const void *obj)
Definition: outfuncs.c:877
PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached)
Definition: partdesc.c:72
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
Definition: partdesc.c:461
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1079

References Assert(), CacheInvalidateRelcache(), CacheInvalidateRelcacheByRelid(), CatalogTupleUpdate(), CommandCounterIncrement(), CStringGetTextDatum, elog(), ERROR, get_default_oid_from_partdesc(), GETSTRUCT, heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, PartitionBoundSpec::is_default, nodeToString(), ObjectIdGetDatum(), OidIsValid, RelationGetDescr, RelationGetPartitionDesc(), RelationGetRelid, RELOID, RowExclusiveLock, SearchSysCacheCopy1, SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), and update_default_partition_oid().

Referenced by ATExecAttachPartition(), and DefineRelation().

◆ StorePartitionKey()

void StorePartitionKey ( Relation  rel,
char  strategy,
int16  partnatts,
AttrNumber partattrs,
List partexprs,
Oid partopclass,
Oid partcollation 
)

Definition at line 3313 of file heap.c.

3320 {
3321  int i;
3322  int2vector *partattrs_vec;
3323  oidvector *partopclass_vec;
3324  oidvector *partcollation_vec;
3325  Datum partexprDatum;
3326  Relation pg_partitioned_table;
3327  HeapTuple tuple;
3328  Datum values[Natts_pg_partitioned_table];
3329  bool nulls[Natts_pg_partitioned_table] = {0};
3330  ObjectAddress myself;
3331  ObjectAddress referenced;
3332  ObjectAddresses *addrs;
3333 
3334  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3335 
3336  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3337  partattrs_vec = buildint2vector(partattrs, partnatts);
3338  partopclass_vec = buildoidvector(partopclass, partnatts);
3339  partcollation_vec = buildoidvector(partcollation, partnatts);
3340 
3341  /* Convert the expressions (if any) to a text datum */
3342  if (partexprs)
3343  {
3344  char *exprString;
3345 
3346  exprString = nodeToString(partexprs);
3347  partexprDatum = CStringGetTextDatum(exprString);
3348  pfree(exprString);
3349  }
3350  else
3351  partexprDatum = (Datum) 0;
3352 
3353  pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
3354 
3355  /* Only this can ever be NULL */
3356  if (!partexprDatum)
3357  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3358 
3359  values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
3360  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3361  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3362  values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
3363  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3364  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3365  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3366  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3367 
3368  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3369 
3370  CatalogTupleInsert(pg_partitioned_table, tuple);
3371  table_close(pg_partitioned_table, RowExclusiveLock);
3372 
3373  /* Mark this relation as dependent on a few things as follows */
3374  addrs = new_object_addresses();
3375  ObjectAddressSet(myself, RelationRelationId, RelationGetRelid(rel));
3376 
3377  /* Operator class and collation per key column */
3378  for (i = 0; i < partnatts; i++)
3379  {
3380  ObjectAddressSet(referenced, OperatorClassRelationId, partopclass[i]);
3381  add_exact_object_address(&referenced, addrs);
3382 
3383  /* The default collation is pinned, so don't bother recording it */
3384  if (OidIsValid(partcollation[i]) &&
3385  partcollation[i] != DEFAULT_COLLATION_OID)
3386  {
3387  ObjectAddressSet(referenced, CollationRelationId, partcollation[i]);
3388  add_exact_object_address(&referenced, addrs);
3389  }
3390  }
3391 
3393  free_object_addresses(addrs);
3394 
3395  /*
3396  * The partitioning columns are made internally dependent on the table,
3397  * because we cannot drop any of them without dropping the whole table.
3398  * (ATExecDropColumn independently enforces that, but it's not bulletproof
3399  * so we need the dependencies too.)
3400  */
3401  for (i = 0; i < partnatts; i++)
3402  {
3403  if (partattrs[i] == 0)
3404  continue; /* ignore expressions here */
3405 
3406  ObjectAddressSubSet(referenced, RelationRelationId,
3407  RelationGetRelid(rel), partattrs[i]);
3408  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
3409  }
3410 
3411  /*
3412  * Also consider anything mentioned in partition expressions. External
3413  * references (e.g. functions) get NORMAL dependencies. Table columns
3414  * mentioned in the expressions are handled the same as plain partitioning
3415  * columns, i.e. they become internally dependent on the whole table.
3416  */
3417  if (partexprs)
3419  (Node *) partexprs,
3420  RelationGetRelid(rel),
3423  true /* reverse the self-deps */ );
3424 
3425  /*
3426  * We must invalidate the relcache so that the next
3427  * CommandCounterIncrement() will cause the same to be rebuilt using the
3428  * information in just created catalog entry.
3429  */
3431 }
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
Definition: dependency.c:1645
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:114
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:86
Definition: c.h:699
Definition: c.h:710

References add_exact_object_address(), Assert(), buildint2vector(), buildoidvector(), CacheInvalidateRelcache(), CatalogTupleInsert(), CharGetDatum(), CStringGetTextDatum, DEPENDENCY_INTERNAL, DEPENDENCY_NORMAL, free_object_addresses(), heap_form_tuple(), i, Int16GetDatum(), InvalidOid, new_object_addresses(), nodeToString(), ObjectAddressSet, ObjectAddressSubSet, ObjectIdGetDatum(), OidIsValid, pfree(), PointerGetDatum(), RelationData::rd_rel, record_object_address_dependencies(), recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetDescr, RelationGetRelid, RowExclusiveLock, table_close(), table_open(), and values.

Referenced by DefineRelation().

◆ StoreRelCheck()

static Oid StoreRelCheck ( Relation  rel,
const char *  ccname,
Node expr,
bool  is_validated,
bool  is_local,
int  inhcount,
bool  is_no_inherit,
bool  is_internal 
)
static

Definition at line 2064 of file heap.c.

2067 {
2068  char *ccbin;
2069  List *varList;
2070  int keycount;
2071  int16 *attNos;
2072  Oid constrOid;
2073 
2074  /*
2075  * Flatten expression to string form for storage.
2076  */
2077  ccbin = nodeToString(expr);
2078 
2079  /*
2080  * Find columns of rel that are used in expr
2081  *
2082  * NB: pull_var_clause is okay here only because we don't allow subselects
2083  * in check constraints; it would fail to examine the contents of
2084  * subselects.
2085  */
2086  varList = pull_var_clause(expr, 0);
2087  keycount = list_length(varList);
2088 
2089  if (keycount > 0)
2090  {
2091  ListCell *vl;
2092  int i = 0;
2093 
2094  attNos = (int16 *) palloc(keycount * sizeof(int16));
2095  foreach(vl, varList)
2096  {
2097  Var *var = (Var *) lfirst(vl);
2098  int j;
2099 
2100  for (j = 0; j < i; j++)
2101  if (attNos[j] == var->varattno)
2102  break;
2103  if (j == i)
2104  attNos[i++] = var->varattno;
2105  }
2106  keycount = i;
2107  }
2108  else
2109  attNos = NULL;
2110 
2111  /*
2112  * Partitioned tables do not contain any rows themselves, so a NO INHERIT
2113  * constraint makes no sense.
2114  */
2115  if (is_no_inherit &&
2116  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2117  ereport(ERROR,
2118  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2119  errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
2120  RelationGetRelationName(rel))));
2121 
2122  /*
2123  * Create the Check Constraint
2124  */
2125  constrOid =
2126  CreateConstraintEntry(ccname, /* Constraint Name */
2127  RelationGetNamespace(rel), /* namespace */
2128  CONSTRAINT_CHECK, /* Constraint Type */
2129  false, /* Is Deferrable */
2130  false, /* Is Deferred */
2131  is_validated,
2132  InvalidOid, /* no parent constraint */
2133  RelationGetRelid(rel), /* relation */
2134  attNos, /* attrs in the constraint */
2135  keycount, /* # key attrs in the constraint */
2136  keycount, /* # total attrs in the constraint */
2137  InvalidOid, /* not a domain constraint */
2138  InvalidOid, /* no associated index */
2139  InvalidOid, /* Foreign key fields */
2140  NULL,
2141  NULL,
2142  NULL,
2143  NULL,
2144  0,
2145  ' ',
2146  ' ',
2147  NULL,
2148  0,
2149  ' ',
2150  NULL, /* not an exclusion constraint */
2151  expr, /* Tree form of check constraint */
2152  ccbin, /* Binary form of check constraint */
2153  is_local, /* conislocal */
2154  inhcount, /* coninhcount */
2155  is_no_inherit, /* connoinherit */
2156  is_internal); /* internally constructed? */
2157 
2158  pfree(ccbin);
2159 
2160  return constrOid;
2161 }
signed short int16
Definition: c.h:477
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
Definition: pg_constraint.c:50

References CreateConstraintEntry(), ereport, errcode(), errmsg(), ERROR, i, InvalidOid, j, lfirst, list_length(), nodeToString(), palloc(), pfree(), pull_var_clause(), RelationData::rd_rel, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, and Var::varattno.

Referenced by AddRelationNewConstraints(), and StoreConstraints().

◆ SystemAttributeByName()

const FormData_pg_attribute* SystemAttributeByName ( const char *  attname)

Definition at line 251 of file heap.c.

252 {
253  int j;
254 
255  for (j = 0; j < (int) lengthof(SysAtt); j++)
256  {
257  const FormData_pg_attribute *att = SysAtt[j];
258 
259  if (strcmp(NameStr(att->attname), attname) == 0)
260  return att;
261  }
262 
263  return NULL;
264 }

References attname, FormData_pg_attribute, j, lengthof, NameStr, and SysAtt.

Referenced by CheckAttributeNamesTypes(), expanded_record_lookup_field(), specialAttNum(), SPI_fnumber(), and transformIndexConstraint().

◆ SystemAttributeDefinition()

const FormData_pg_attribute* SystemAttributeDefinition ( AttrNumber  attno)

Definition at line 239 of file heap.c.

240 {
241  if (attno >= 0 || attno < -(int) lengthof(SysAtt))
242  elog(ERROR, "invalid system attribute number %d", attno);
243  return SysAtt[-attno - 1];
244 }

References elog(), ERROR, lengthof, and SysAtt.

Referenced by attnumAttName(), attnumTypeId(), build_index_tlist(), scanNSItemForColumn(), SPI_fname(), SPI_gettype(), SPI_gettypeid(), SPI_getvalue(), and transformIndexConstraint().

Variable Documentation

◆ a1

const FormData_pg_attribute a1
static
Initial value:
= {
.attname = {"ctid"},
.atttypid = TIDOID,
.attlen = sizeof(ItemPointerData),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = false,
.attalign = TYPALIGN_SHORT,
.attstorage = TYPSTORAGE_PLAIN,
.attnotnull = true,
.attislocal = true,
}
struct ItemPointerData ItemPointerData
char attstorage
Definition: pg_attribute.h:117
bool attbyval
Definition: pg_attribute.h:103
char attalign
Definition: pg_attribute.h:109
bool attnotnull
Definition: pg_attribute.h:130
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21

Definition at line 141 of file heap.c.

Referenced by aclitem_eq(), aclitem_match(), aclitemComparator(), brin_minmax_multi_distance_float4(), brin_minmax_multi_distance_float8(), brin_minmax_multi_distance_int2(), brin_minmax_multi_distance_int4(), brin_minmax_multi_distance_int8(), brin_minmax_multi_distance_numeric(), brin_minmax_multi_distance_uuid(), build_distances(), cmpaffix(), deccall2(), deccall3(), distance_1D(), entryIndexByFrequencyCmp(), evalLazyFunc(), float8_qsort_cmp(), inet_merge(), inet_same_family(), int4gcd_internal(), int8gcd_internal(), macaddr8_cmp(), macaddr8_cmp_internal(), macaddr8_eq(), macaddr8_ge(), macaddr8_gt(), macaddr8_le(), macaddr8_lt(), macaddr8_ne(), macaddr_cmp(), macaddr_cmp_internal(), macaddr_eq(), macaddr_ge(), macaddr_gt(), macaddr_le(), macaddr_lt(), macaddr_ne(), MergeAffix(), network_cmp(), network_cmp_internal(), network_eq(), network_ge(), network_gt(), network_larger(), network_le(), network_lt(), network_ne(), network_overlap(), network_smaller(), network_sub(), network_subeq(), network_sup(), network_supeq(), packArcInfoCmp(), range_bound_qsort_cmp(), and sqrt_var().

◆ a2

const FormData_pg_attribute a2
static
Initial value:
= {
.attname = {"xmin"},
.atttypid = XIDOID,
.attlen = sizeof(TransactionId),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = true,
.attalign = TYPALIGN_INT,
.attstorage = TYPSTORAGE_PLAIN,
.attnotnull = true,
.attislocal = true,
}
#define MinTransactionIdAttributeNumber
Definition: sysattr.h:22

Definition at line 155 of file heap.c.

Referenced by aclitem_eq(), aclitem_match(), aclitemComparator(), brin_minmax_multi_distance_float4(), brin_minmax_multi_distance_float8(), brin_minmax_multi_distance_int2(), brin_minmax_multi_distance_int4(), brin_minmax_multi_distance_int8(), brin_minmax_multi_distance_numeric(), brin_minmax_multi_distance_uuid(), build_distances(), clonesuccessorstates(), cmpaffix(), deccall2(), deccall3(), distance_1D(), entryIndexByFrequencyCmp(), evalLazyFunc(), float8_qsort_cmp(), inet_merge(), inet_same_family(), int4gcd_internal(), int8gcd_internal(), macaddr8_cmp(), macaddr8_cmp_internal(), macaddr8_eq(), macaddr8_ge(), macaddr8_gt(), macaddr8_le(), macaddr8_lt(), macaddr8_ne(), macaddr_cmp(), macaddr_cmp_internal(), macaddr_eq(), macaddr_ge(), macaddr_gt(), macaddr_le(), macaddr_lt(), macaddr_ne(), MergeAffix(), network_cmp(), network_cmp_internal(), network_eq(), network_ge(), network_gt(), network_larger(), network_le(), network_lt(), network_ne(), network_overlap(), network_smaller(), network_sub(), network_subeq(), network_sup(), network_supeq(), packArcInfoCmp(), and range_bound_qsort_cmp().

◆ a3

const FormData_pg_attribute a3
static
Initial value:
= {
.attname = {"cmin"},
.atttypid = CIDOID,
.attlen = sizeof(CommandId),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = true,
.attalign = TYPALIGN_INT,
.attstorage = TYPSTORAGE_PLAIN,
.attnotnull = true,
.attislocal = true,
}
uint32 CommandId
Definition: c.h:650
#define MinCommandIdAttributeNumber
Definition: sysattr.h:23

Definition at line 169 of file heap.c.

◆ a4

const FormData_pg_attribute a4
static
Initial value:
= {
.attname = {"xmax"},
.atttypid = XIDOID,
.attlen = sizeof(TransactionId),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = true,
.attalign = TYPALIGN_INT,
.attstorage = TYPSTORAGE_PLAIN,
.attnotnull = true,
.attislocal = true,
}
#define MaxTransactionIdAttributeNumber
Definition: sysattr.h:24

Definition at line 183 of file heap.c.

◆ a5

const FormData_pg_attribute a5
static
Initial value:
= {
.attname = {"cmax"},
.atttypid = CIDOID,
.attlen = sizeof(CommandId),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = true,
.attalign = TYPALIGN_INT,
.attstorage = TYPSTORAGE_PLAIN,
.attnotnull = true,
.attislocal = true,
}
#define MaxCommandIdAttributeNumber
Definition: sysattr.h:25

Definition at line 197 of file heap.c.

◆ a6

const FormData_pg_attribute a6
static
Initial value:
= {
.attname = {"tableoid"},
.atttypid = OIDOID,
.attlen = sizeof(Oid),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = true,
.attalign = TYPALIGN_INT,
.attstorage = TYPSTORAGE_PLAIN,
.attnotnull = true,
.attislocal = true,
}
#define TableOidAttributeNumber
Definition: sysattr.h:26

Definition at line 217 of file heap.c.

◆ binary_upgrade_next_heap_pg_class_oid

Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid

Definition at line 79 of file heap.c.

Referenced by binary_upgrade_set_next_heap_pg_class_oid(), and heap_create_with_catalog().

◆ binary_upgrade_next_heap_pg_class_relfilenumber

RelFileNumber binary_upgrade_next_heap_pg_class_relfilenumber = InvalidRelFileNumber

◆ binary_upgrade_next_toast_pg_class_oid

Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid

◆ binary_upgrade_next_toast_pg_class_relfilenumber

RelFileNumber binary_upgrade_next_toast_pg_class_relfilenumber = InvalidRelFileNumber

Definition at line 82 of file heap.c.

Referenced by binary_upgrade_set_next_toast_relfilenode(), and heap_create_with_catalog().

◆ SysAtt

const FormData_pg_attribute* SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6}
static

Definition at line 231 of file heap.c.

Referenced by AddNewAttributeTuples(), SystemAttributeByName(), and SystemAttributeDefinition().