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, Oid relfilenode, 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_heap_pg_class_relfilenode = InvalidOid
 
Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid
 
Oid binary_upgrade_next_toast_pg_class_relfilenode = InvalidOid
 
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 801 of file heap.c.

804 {
805  Relation rel;
806  CatalogIndexState indstate;
807  int natts = tupdesc->natts;
808  ObjectAddress myself,
809  referenced;
810 
811  /*
812  * open pg_attribute and its indexes.
813  */
814  rel = table_open(AttributeRelationId, RowExclusiveLock);
815 
816  indstate = CatalogOpenIndexes(rel);
817 
818  /* set stats detail level to a sane default */
819  for (int i = 0; i < natts; i++)
820  tupdesc->attrs[i].attstattarget = -1;
821  InsertPgAttributeTuples(rel, tupdesc, new_rel_oid, NULL, indstate);
822 
823  /* add dependencies on their datatypes and collations */
824  for (int i = 0; i < natts; i++)
825  {
826  /* Add dependency info */
827  ObjectAddressSubSet(myself, RelationRelationId, new_rel_oid, i + 1);
828  ObjectAddressSet(referenced, TypeRelationId,
829  tupdesc->attrs[i].atttypid);
830  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
831 
832  /* The default collation is pinned, so don't bother recording it */
833  if (OidIsValid(tupdesc->attrs[i].attcollation) &&
834  tupdesc->attrs[i].attcollation != DEFAULT_COLLATION_OID)
835  {
836  ObjectAddressSet(referenced, CollationRelationId,
837  tupdesc->attrs[i].attcollation);
838  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
839  }
840  }
841 
842  /*
843  * Next we add the system attributes. Skip OID if rel has no OIDs. Skip
844  * all for a view or type relation. We don't bother with making datatype
845  * dependencies here, since presumably all these types are pinned.
846  */
847  if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
848  {
849  TupleDesc td;
850 
852 
853  InsertPgAttributeTuples(rel, td, new_rel_oid, NULL, indstate);
854  FreeTupleDesc(td);
855  }
856 
857  /*
858  * clean up
859  */
860  CatalogCloseIndexes(indstate);
861 
863 }
#define lengthof(array)
Definition: c.h:734
#define OidIsValid(objectId)
Definition: c.h:710
@ 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:694
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:191
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:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
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 952 of file heap.c.

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

1017 {
1018  return
1019  TypeCreate(new_row_type, /* optional predetermined OID */
1020  typeName, /* type name */
1021  typeNamespace, /* type namespace */
1022  new_rel_oid, /* relation oid */
1023  new_rel_kind, /* relation kind */
1024  ownerid, /* owner's ID */
1025  -1, /* internal size (varlena) */
1026  TYPTYPE_COMPOSITE, /* type-type (composite) */
1027  TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
1028  false, /* composite types are never preferred */
1029  DEFAULT_TYPDELIM, /* default array delimiter */
1030  F_RECORD_IN, /* input procedure */
1031  F_RECORD_OUT, /* output procedure */
1032  F_RECORD_RECV, /* receive procedure */
1033  F_RECORD_SEND, /* send procedure */
1034  InvalidOid, /* typmodin procedure - none */
1035  InvalidOid, /* typmodout procedure - none */
1036  InvalidOid, /* analyze procedure - default */
1037  InvalidOid, /* subscript procedure - none */
1038  InvalidOid, /* array element type - irrelevant */
1039  false, /* this is not an array type */
1040  new_array_type, /* array type if any */
1041  InvalidOid, /* domain base type - irrelevant */
1042  NULL, /* default value - none */
1043  NULL, /* default binary representation */
1044  false, /* passed by reference */
1045  TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1046  TYPSTORAGE_EXTENDED, /* fully TOASTable */
1047  -1, /* typmod */
1048  0, /* array dimensions for typBaseType */
1049  false, /* Type NOT NULL */
1050  InvalidOid); /* rowtypes never have a collation */
1051 }
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:198
#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 2254 of file heap.c.

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

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 2730 of file heap.c.

2731 {
2732  check_nested_generated_walker(node, pstate);
2733 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:2688

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 2688 of file heap.c.

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

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 452 of file heap.c.

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

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

2826 {
2827  Node *expr;
2828 
2829  /*
2830  * Transform raw parsetree to executable expression.
2831  */
2832  expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
2833 
2834  /*
2835  * Make sure it yields a boolean result.
2836  */
2837  expr = coerce_to_boolean(pstate, expr, "CHECK");
2838 
2839  /*
2840  * Take care of collations.
2841  */
2842  assign_expr_collations(pstate, expr);
2843 
2844  /*
2845  * Make sure no outside relations are referred to (this is probably dead
2846  * code now that add_missing_from is history).
2847  */
2848  if (list_length(pstate->p_rtable) != 1)
2849  ereport(ERROR,
2850  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2851  errmsg("only table \"%s\" can be referenced in check constraint",
2852  relname)));
2853 
2854  return expr;
2855 }
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:112
@ 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 2748 of file heap.c.

2754 {
2755  Node *expr;
2756 
2757  Assert(raw_default != NULL);
2758 
2759  /*
2760  * Transform raw parsetree to executable expression.
2761  */
2762  expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
2763 
2764  if (attgenerated)
2765  {
2766  check_nested_generated(pstate, expr);
2767 
2768  if (contain_mutable_functions(expr))
2769  ereport(ERROR,
2770  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2771  errmsg("generation expression is not immutable")));
2772  }
2773  else
2774  {
2775  /*
2776  * For a default expression, transformExpr() should have rejected
2777  * column references.
2778  */
2779  Assert(!contain_var_clause(expr));
2780  }
2781 
2782  /*
2783  * Coerce the expression to the correct type and typmod, if given. This
2784  * should match the parser's processing of non-defaulted expressions ---
2785  * see transformAssignedExpr().
2786  */
2787  if (OidIsValid(atttypid))
2788  {
2789  Oid type_id = exprType(expr);
2790 
2791  expr = coerce_to_target_type(pstate, expr, type_id,
2792  atttypid, atttypmod,
2795  -1);
2796  if (expr == NULL)
2797  ereport(ERROR,
2798  (errcode(ERRCODE_DATATYPE_MISMATCH),
2799  errmsg("column \"%s\" is of type %s"
2800  " but default expression is of type %s",
2801  attname,
2802  format_type_be(atttypid),
2803  format_type_be(type_id)),
2804  errhint("You will need to rewrite or cast the expression.")));
2805  }
2806 
2807  /*
2808  * Finally, take care of collations in the finished expression.
2809  */
2810  assign_expr_collations(pstate, expr);
2811 
2812  return expr;
2813 }
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:368
static void check_nested_generated(ParseState *pstate, Node *node)
Definition: heap.c:2730
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
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:494
@ COERCION_ASSIGNMENT
Definition: primnodes.h:473
bool contain_var_clause(Node *node)
Definition: var.c:400

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 2861 of file heap.c.

2862 {
2863  HeapTuple tup;
2864  SysScanDesc scan;
2865  ScanKeyData key[1];
2866  Relation statrel;
2867 
2868  statrel = table_open(StatisticRelationId, RowExclusiveLock);
2869 
2870  /* Now search for stat records */
2871  ScanKeyInit(&key[0],
2872  Anum_pg_statistic_starelid,
2873  BTEqualStrategyNumber, F_OIDEQ,
2874  ObjectIdGetDatum(fromrelid));
2875 
2876  scan = systable_beginscan(statrel, StatisticRelidAttnumInhIndexId,
2877  true, NULL, 1, key);
2878 
2879  while (HeapTupleIsValid((tup = systable_getnext(scan))))
2880  {
2881  Form_pg_statistic statform;
2882 
2883  /* make a modifiable copy */
2884  tup = heap_copytuple(tup);
2885  statform = (Form_pg_statistic) GETSTRUCT(tup);
2886 
2887  /* update the copy of the tuple and insert it */
2888  statform->starelid = torelid;
2889  CatalogTupleInsert(statrel, tup);
2890 
2891  heap_freetuple(tup);
2892  }
2893 
2894  systable_endscan(scan);
2895 
2896  table_close(statrel, RowExclusiveLock);
2897 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:598
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:505
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:386
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:649
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:135
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

References BTEqualStrategyNumber, CatalogTupleInsert(), 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:350
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 }
#define elog(elevel,...)
Definition: elog.h:218
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
@ 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 }
#define Int16GetDatum(X)
Definition: postgres.h:495
#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().

Referenced by DefineQueryRewrite().

◆ heap_create()

Relation heap_create ( const char *  relname,
Oid  relnamespace,
Oid  reltablespace,
Oid  relid,
Oid  relfilenode,
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 relfilenode is unspecified by the caller then create storage
345  * with oid same as relid.
346  */
347  if (!OidIsValid(relfilenode))
348  relfilenode = 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  relfilenode,
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_node, 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  return rel;
407 }
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:3326
#define IsNormalProcessingMode()
Definition: miscadmin.h:408
#define InvalidMultiXactId
Definition: multixact.h:24
void recordDependencyOnTablespace(Oid classId, Oid objectId, Oid tablespace)
Definition: pg_shdepend.c:360
Relation RelationBuildLocalRelation(const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid accessmtd, Oid relfilenode, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
Definition: relcache.c:3457
SMgrRelation RelationCreateStorage(RelFileNode rnode, char relpersistence, bool register_delete)
Definition: storage.c:120
RelFileNode rd_node
Definition: rel.h:56
static void table_relation_set_new_filenode(Relation rel, const RelFileNode *newrnode, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition: tableam.h:1592
#define InvalidTransactionId
Definition: transam.h:31

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

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 1088 of file heap.c.

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

References add_exact_object_address(), AddNewAttributeTuples(), AddNewRelationTuple(), AddNewRelationType(), Assert(), AssignTypeArrayOid(), binary_upgrade_next_heap_pg_class_oid, binary_upgrade_next_heap_pg_class_relfilenode, binary_upgrade_next_toast_pg_class_oid, binary_upgrade_next_toast_pg_class_relfilenode, 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(), GetNewRelFileNode(), GetSysCacheOid2, heap_create(), InvalidOid, InvokeObjectPostCreateHookArg, IsBinaryUpgrade, IsBootstrapProcessingMode, IsNormalProcessingMode, makeArrayTypeName(), moveArrayTypeName(), new_object_addresses(), NoLock, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum, OidIsValid, ONCOMMIT_NOOP, pfree(), pgstat_create_relation(), PointerGetDatum, RelationData::rd_att, RelationData::rd_rel, record_object_address_dependencies(), recordDependencyOnCurrentExtension(), recordDependencyOnNewAcl(), recordDependencyOnOwner(), register_on_commit_action(), RelationGetRelid, 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 1759 of file heap.c.

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

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 3001 of file heap.c.

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

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 3086 of file heap.c.

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

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 3181 of file heap.c.

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

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

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 694 of file heap.c.

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

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 879 of file heap.c.

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

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 2504 of file heap.c.

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

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

2954 {
2955  ListCell *indlist;
2956 
2957  /* Ask the relcache to produce a list of the indexes of the rel */
2958  foreach(indlist, RelationGetIndexList(heapRelation))
2959  {
2960  Oid indexId = lfirst_oid(indlist);
2961  Relation currentIndex;
2962  IndexInfo *indexInfo;
2963 
2964  /* Open the index relation; use exclusive lock, just to be sure */
2965  currentIndex = index_open(indexId, AccessExclusiveLock);
2966 
2967  /*
2968  * Fetch info needed for index_build. Since we know there are no
2969  * tuples that actually need indexing, we can use a dummy IndexInfo.
2970  * This is slightly cheaper to build, but the real point is to avoid
2971  * possibly running user-defined code in index expressions or
2972  * predicates. We might be getting invoked during ON COMMIT
2973  * processing, and we don't want to run any such code then.
2974  */
2975  indexInfo = BuildDummyIndexInfo(currentIndex);
2976 
2977  /*
2978  * Now truncate the actual file (and discard buffers).
2979  */
2980  RelationTruncate(currentIndex, 0);
2981 
2982  /* Initialize the index and rebuild */
2983  /* Note: we do not need to re-establish pkey setting */
2984  index_build(heapRelation, currentIndex, indexInfo, true, false);
2985 
2986  /* We're done with this index */
2987  index_close(currentIndex, NoLock);
2988  }
2989 }
IndexInfo * BuildDummyIndexInfo(Relation index)
Definition: index.c:2478
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isreindex, bool parallel)
Definition: index.c:2943
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:4675
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];
1713  bool nullsAtt[Natts_pg_attribute];
1714  bool replacesAtt[Natts_pg_attribute];
1715 
1716  /* update the tuple - set atthasmissing and attmissingval */
1717  MemSet(valuesAtt, 0, sizeof(valuesAtt));
1718  MemSet(nullsAtt, false, sizeof(nullsAtt));
1719  MemSet(replacesAtt, false, sizeof(replacesAtt));
1720 
1721  valuesAtt[Anum_pg_attribute_atthasmissing - 1] =
1722  BoolGetDatum(false);
1723  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
1724  valuesAtt[Anum_pg_attribute_attmissingval - 1] = (Datum) 0;
1725  nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
1726  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
1727 
1728  tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
1729  valuesAtt, nullsAtt, replacesAtt);
1730  }
1731 
1732  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1733  }
1734 
1735  /*
1736  * Because updating the pg_attribute row will trigger a relcache flush for
1737  * the target relation, we need not do anything else to notify other
1738  * backends of the change.
1739  */
1740 
1741  table_close(attr_rel, RowExclusiveLock);
1742 
1743  if (attnum > 0)
1744  RemoveStatistics(relid, attnum);
1745 
1746  relation_close(rel, NoLock);
1747 }
#define MemSet(start, val, len)
Definition: c.h:1008
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define NAMEDATALEN
#define snprintf
Definition: port.h:225
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:181

References AccessExclusiveLock, attnum, ATTNUM, BoolGetDatum, CatalogTupleDelete(), CatalogTupleUpdate(), elog, ERROR, GETSTRUCT, heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum, InvalidOid, MemSet, 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 3435 of file heap.c.

3436 {
3437  Relation rel;
3438  HeapTuple tuple;
3439 
3440  rel = table_open(PartitionedRelationId, RowExclusiveLock);
3441 
3442  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3443  if (!HeapTupleIsValid(tuple))
3444  elog(ERROR, "cache lookup failed for partition key of relation %u",
3445  relid);
3446 
3447  CatalogTupleDelete(rel, &tuple->t_self);
3448 
3449  ReleaseSysCache(tuple);
3451 }
@ 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 2906 of file heap.c.

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

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 2007 of file heap.c.

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

References AccessExclusiveLock, attname, BoolGetDatum, CatalogTupleUpdate(), CStringGetDatum, elog, ERROR, GETSTRUCT, heap_modify_tuple(), HeapTupleIsValid, Int32GetDatum, MemSet, 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 2654 of file heap.c.

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

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 2182 of file heap.c.

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

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 3466 of file heap.c.

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

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 3308 of file heap.c.

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

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, MemSet, 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 2072 of file heap.c.

2075 {
2076  char *ccbin;
2077  List *varList;
2078  int keycount;
2079  int16 *attNos;
2080  Oid constrOid;
2081 
2082  /*
2083  * Flatten expression to string form for storage.
2084  */
2085  ccbin = nodeToString(expr);
2086 
2087  /*
2088  * Find columns of rel that are used in expr
2089  *
2090  * NB: pull_var_clause is okay here only because we don't allow subselects
2091  * in check constraints; it would fail to examine the contents of
2092  * subselects.
2093  */
2094  varList = pull_var_clause(expr, 0);
2095  keycount = list_length(varList);
2096 
2097  if (keycount > 0)
2098  {
2099  ListCell *vl;
2100  int i = 0;
2101 
2102  attNos = (int16 *) palloc(keycount * sizeof(int16));
2103  foreach(vl, varList)
2104  {
2105  Var *var = (Var *) lfirst(vl);
2106  int j;
2107 
2108  for (j = 0; j < i; j++)
2109  if (attNos[j] == var->varattno)
2110  break;
2111  if (j == i)
2112  attNos[i++] = var->varattno;
2113  }
2114  keycount = i;
2115  }
2116  else
2117  attNos = NULL;
2118 
2119  /*
2120  * Partitioned tables do not contain any rows themselves, so a NO INHERIT
2121  * constraint makes no sense.
2122  */
2123  if (is_no_inherit &&
2124  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2125  ereport(ERROR,
2126  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2127  errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
2128  RelationGetRelationName(rel))));
2129 
2130  /*
2131  * Create the Check Constraint
2132  */
2133  constrOid =
2134  CreateConstraintEntry(ccname, /* Constraint Name */
2135  RelationGetNamespace(rel), /* namespace */
2136  CONSTRAINT_CHECK, /* Constraint Type */
2137  false, /* Is Deferrable */
2138  false, /* Is Deferred */
2139  is_validated,
2140  InvalidOid, /* no parent constraint */
2141  RelationGetRelid(rel), /* relation */
2142  attNos, /* attrs in the constraint */
2143  keycount, /* # key attrs in the constraint */
2144  keycount, /* # total attrs in the constraint */
2145  InvalidOid, /* not a domain constraint */
2146  InvalidOid, /* no associated index */
2147  InvalidOid, /* Foreign key fields */
2148  NULL,
2149  NULL,
2150  NULL,
2151  NULL,
2152  0,
2153  ' ',
2154  ' ',
2155  NULL,
2156  0,
2157  ' ',
2158  NULL, /* not an exclusion constraint */
2159  expr, /* Tree form of check constraint */
2160  ccbin, /* Binary form of check constraint */
2161  is_local, /* conislocal */
2162  inhcount, /* coninhcount */
2163  is_no_inherit, /* connoinherit */
2164  is_internal); /* internally constructed? */
2165 
2166  pfree(ccbin);
2167 
2168  return constrOid;
2169 }
signed short int16
Definition: c.h:428
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:126
bool attbyval
Definition: pg_attribute.h:112
char attalign
Definition: pg_attribute.h:118
bool attnotnull
Definition: pg_attribute.h:139
#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:601
#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_relfilenode

Oid binary_upgrade_next_heap_pg_class_relfilenode = InvalidOid

Definition at line 80 of file heap.c.

Referenced by binary_upgrade_set_next_heap_relfilenode(), and heap_create_with_catalog().

◆ binary_upgrade_next_toast_pg_class_oid

Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid

◆ binary_upgrade_next_toast_pg_class_relfilenode

Oid binary_upgrade_next_toast_pg_class_relfilenode = InvalidOid

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().