PostgreSQL Source Code  git master
heap.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/relation.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "access/tableam.h"
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.h"
#include "catalog/dependency.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 "catalog/storage_xlog.h"
#include "commands/tablecmds.h"
#include "commands/typecmds.h"
#include "executor/executor.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 "storage/lmgr.h"
#include "storage/predicate.h"
#include "storage/smgr.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/partcache.h"
#include "utils/ruleutils.h"
#include "utils/snapmgr.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)
 
void CheckAttributeNamesTypes (TupleDesc tupdesc, char relkind, int flags)
 
void CheckAttributeType (const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
 
void InsertPgAttributeTuple (Relation pg_attribute_rel, Form_pg_attribute new_attribute, 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 RemoveAttrDefault (Oid relid, AttrNumber attnum, DropBehavior behavior, bool complain, bool internal)
 
void RemoveAttrDefaultById (Oid attrdefId)
 
void heap_drop_with_catalog (Oid relid)
 
void RelationClearMissing (Relation rel)
 
void SetAttrMissing (Oid relid, char *attname, char *value)
 
Oid StoreAttrDefault (Relation rel, AttrNumber attnum, Node *expr, bool is_internal, bool add_column_mode)
 
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 RemoveStatistics (Oid relid, AttrNumber attnum)
 
static void RelationTruncateIndexes (Relation heapRelation)
 
void heap_truncate (List *relids)
 
void heap_truncate_one_rel (Relation rel)
 
void heap_truncate_check_FKs (List *relations, bool tempTables)
 
Listheap_truncate_find_FKs (List *relationIds)
 
void StorePartitionKey (Relation rel, char strategy, int16 partnatts, AttrNumber *partattrs, List *partexprs, Oid *partopclass, Oid *partcollation)
 
void RemovePartitionKeyByRelId (Oid relid)
 
void StorePartitionBound (Relation rel, Relation parent, PartitionBoundSpec *bound)
 

Variables

Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid
 
Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid
 
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 787 of file heap.c.

References CatalogCloseIndexes(), CatalogOpenIndexes(), DEPENDENCY_NORMAL, FormData_pg_attribute, i, InsertPgAttributeTuple(), lengthof, TupleDescData::natts, ObjectAddressSet, ObjectAddressSubSet, OidIsValid, recordDependencyOn(), RowExclusiveLock, SysAtt, table_close(), table_open(), and TupleDescAttr.

Referenced by heap_create_with_catalog().

790 {
791  Form_pg_attribute attr;
792  int i;
793  Relation rel;
794  CatalogIndexState indstate;
795  int natts = tupdesc->natts;
796  ObjectAddress myself,
797  referenced;
798 
799  /*
800  * open pg_attribute and its indexes.
801  */
802  rel = table_open(AttributeRelationId, RowExclusiveLock);
803 
804  indstate = CatalogOpenIndexes(rel);
805 
806  /*
807  * First we add the user attributes. This is also a convenient place to
808  * add dependencies on their datatypes and collations.
809  */
810  for (i = 0; i < natts; i++)
811  {
812  attr = TupleDescAttr(tupdesc, i);
813  /* Fill in the correct relation OID */
814  attr->attrelid = new_rel_oid;
815  /* Make sure this is OK, too */
816  attr->attstattarget = -1;
817 
818  InsertPgAttributeTuple(rel, attr, (Datum) 0, indstate);
819 
820  /* Add dependency info */
821  ObjectAddressSubSet(myself, RelationRelationId, new_rel_oid, i + 1);
822  ObjectAddressSet(referenced, TypeRelationId, attr->atttypid);
823  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
824 
825  /* The default collation is pinned, so don't bother recording it */
826  if (OidIsValid(attr->attcollation) &&
827  attr->attcollation != DEFAULT_COLLATION_OID)
828  {
829  ObjectAddressSet(referenced, CollationRelationId, attr->attcollation);
830  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
831  }
832  }
833 
834  /*
835  * Next we add the system attributes. Skip OID if rel has no OIDs. Skip
836  * all for a view or type relation. We don't bother with making datatype
837  * dependencies here, since presumably all these types are pinned.
838  */
839  if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
840  {
841  for (i = 0; i < (int) lengthof(SysAtt); i++)
842  {
843  FormData_pg_attribute attStruct;
844 
845  memcpy(&attStruct, SysAtt[i], sizeof(FormData_pg_attribute));
846 
847  /* Fill in the correct relation OID in the copied tuple */
848  attStruct.attrelid = new_rel_oid;
849 
850  InsertPgAttributeTuple(rel, &attStruct, (Datum) 0, indstate);
851  }
852  }
853 
854  /*
855  * clean up
856  */
857  CatalogCloseIndexes(indstate);
858 
860 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
#define lengthof(array)
Definition: c.h:668
#define OidIsValid(objectId)
Definition: c.h:644
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
uintptr_t Datum
Definition: postgres.h:367
FormData_pg_attribute
Definition: pg_attribute.h:177
static const FormData_pg_attribute * SysAtt[]
Definition: heap.c:241
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:42
void InsertPgAttributeTuple(Relation pg_attribute_rel, Form_pg_attribute new_attribute, Datum attoptions, CatalogIndexState indstate)
Definition: heap.c:726
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
Definition: objectaddress.h:33
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
int i
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:60
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

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

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

Referenced by heap_create_with_catalog().

960 {
961  Form_pg_class new_rel_reltup;
962 
963  /*
964  * first we update some of the information in our uncataloged relation's
965  * relation descriptor.
966  */
967  new_rel_reltup = new_rel_desc->rd_rel;
968 
969  switch (relkind)
970  {
971  case RELKIND_RELATION:
972  case RELKIND_MATVIEW:
973  case RELKIND_INDEX:
974  case RELKIND_TOASTVALUE:
975  /* The relation is real, but as yet empty */
976  new_rel_reltup->relpages = 0;
977  new_rel_reltup->reltuples = 0;
978  new_rel_reltup->relallvisible = 0;
979  break;
980  case RELKIND_SEQUENCE:
981  /* Sequences always have a known size */
982  new_rel_reltup->relpages = 1;
983  new_rel_reltup->reltuples = 1;
984  new_rel_reltup->relallvisible = 0;
985  break;
986  default:
987  /* Views, etc, have no disk storage */
988  new_rel_reltup->relpages = 0;
989  new_rel_reltup->reltuples = 0;
990  new_rel_reltup->relallvisible = 0;
991  break;
992  }
993 
994  new_rel_reltup->relfrozenxid = relfrozenxid;
995  new_rel_reltup->relminmxid = relminmxid;
996  new_rel_reltup->relowner = relowner;
997  new_rel_reltup->reltype = new_type_oid;
998  new_rel_reltup->reloftype = reloftype;
999 
1000  /* relispartition is always set by updating this tuple later */
1001  new_rel_reltup->relispartition = false;
1002 
1003  new_rel_desc->rd_att->tdtypeid = new_type_oid;
1004 
1005  /* Now build and insert the tuple */
1006  InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid,
1007  relacl, reloptions);
1008 }
Form_pg_class rd_rel
Definition: rel.h:109
void InsertPgClassTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
Definition: heap.c:876
TupleDesc rd_att
Definition: rel.h:110
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
Oid tdtypeid
Definition: tupdesc.h:82

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

References DEFAULT_TYPDELIM, InvalidOid, and TypeCreate().

Referenced by heap_create_with_catalog().

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

◆ AddRelationNewConstraints()

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

Definition at line 2512 of file heap.c.

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

2519 {
2520  List *cookedConstraints = NIL;
2521  TupleDesc tupleDesc;
2522  TupleConstr *oldconstr;
2523  int numoldchecks;
2524  ParseState *pstate;
2525  ParseNamespaceItem *nsitem;
2526  int numchecks;
2527  List *checknames;
2528  ListCell *cell;
2529  Node *expr;
2530  CookedConstraint *cooked;
2531 
2532  /*
2533  * Get info about existing constraints.
2534  */
2535  tupleDesc = RelationGetDescr(rel);
2536  oldconstr = tupleDesc->constr;
2537  if (oldconstr)
2538  numoldchecks = oldconstr->num_check;
2539  else
2540  numoldchecks = 0;
2541 
2542  /*
2543  * Create a dummy ParseState and insert the target relation as its sole
2544  * rangetable entry. We need a ParseState for transformExpr.
2545  */
2546  pstate = make_parsestate(NULL);
2547  pstate->p_sourcetext = queryString;
2548  nsitem = addRangeTableEntryForRelation(pstate,
2549  rel,
2551  NULL,
2552  false,
2553  true);
2554  addNSItemToQuery(pstate, nsitem, true, true, true);
2555 
2556  /*
2557  * Process column default expressions.
2558  */
2559  foreach(cell, newColDefaults)
2560  {
2561  RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
2562  Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
2563  Oid defOid;
2564 
2565  expr = cookDefault(pstate, colDef->raw_default,
2566  atp->atttypid, atp->atttypmod,
2567  NameStr(atp->attname),
2568  atp->attgenerated);
2569 
2570  /*
2571  * If the expression is just a NULL constant, we do not bother to make
2572  * an explicit pg_attrdef entry, since the default behavior is
2573  * equivalent. This applies to column defaults, but not for
2574  * generation expressions.
2575  *
2576  * Note a nonobvious property of this test: if the column is of a
2577  * domain type, what we'll get is not a bare null Const but a
2578  * CoerceToDomain expr, so we will not discard the default. This is
2579  * critical because the column default needs to be retained to
2580  * override any default that the domain might have.
2581  */
2582  if (expr == NULL ||
2583  (!colDef->generated &&
2584  IsA(expr, Const) &&
2585  castNode(Const, expr)->constisnull))
2586  continue;
2587 
2588  /* If the DEFAULT is volatile we cannot use a missing value */
2589  if (colDef->missingMode && contain_volatile_functions((Node *) expr))
2590  colDef->missingMode = false;
2591 
2592  defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal,
2593  colDef->missingMode);
2594 
2595  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2596  cooked->contype = CONSTR_DEFAULT;
2597  cooked->conoid = defOid;
2598  cooked->name = NULL;
2599  cooked->attnum = colDef->attnum;
2600  cooked->expr = expr;
2601  cooked->skip_validation = false;
2602  cooked->is_local = is_local;
2603  cooked->inhcount = is_local ? 0 : 1;
2604  cooked->is_no_inherit = false;
2605  cookedConstraints = lappend(cookedConstraints, cooked);
2606  }
2607 
2608  /*
2609  * Process constraint expressions.
2610  */
2611  numchecks = numoldchecks;
2612  checknames = NIL;
2613  foreach(cell, newConstraints)
2614  {
2615  Constraint *cdef = (Constraint *) lfirst(cell);
2616  char *ccname;
2617  Oid constrOid;
2618 
2619  if (cdef->contype != CONSTR_CHECK)
2620  continue;
2621 
2622  if (cdef->raw_expr != NULL)
2623  {
2624  Assert(cdef->cooked_expr == NULL);
2625 
2626  /*
2627  * Transform raw parsetree to executable expression, and verify
2628  * it's valid as a CHECK constraint.
2629  */
2630  expr = cookConstraint(pstate, cdef->raw_expr,
2632  }
2633  else
2634  {
2635  Assert(cdef->cooked_expr != NULL);
2636 
2637  /*
2638  * Here, we assume the parser will only pass us valid CHECK
2639  * expressions, so we do no particular checking.
2640  */
2641  expr = stringToNode(cdef->cooked_expr);
2642  }
2643 
2644  /*
2645  * Check name uniqueness, or generate a name if none was given.
2646  */
2647  if (cdef->conname != NULL)
2648  {
2649  ListCell *cell2;
2650 
2651  ccname = cdef->conname;
2652  /* Check against other new constraints */
2653  /* Needed because we don't do CommandCounterIncrement in loop */
2654  foreach(cell2, checknames)
2655  {
2656  if (strcmp((char *) lfirst(cell2), ccname) == 0)
2657  ereport(ERROR,
2659  errmsg("check constraint \"%s\" already exists",
2660  ccname)));
2661  }
2662 
2663  /* save name for future checks */
2664  checknames = lappend(checknames, ccname);
2665 
2666  /*
2667  * Check against pre-existing constraints. If we are allowed to
2668  * merge with an existing constraint, there's no more to do here.
2669  * (We omit the duplicate constraint from the result, which is
2670  * what ATAddCheckConstraint wants.)
2671  */
2672  if (MergeWithExistingConstraint(rel, ccname, expr,
2673  allow_merge, is_local,
2674  cdef->initially_valid,
2675  cdef->is_no_inherit))
2676  continue;
2677  }
2678  else
2679  {
2680  /*
2681  * When generating a name, we want to create "tab_col_check" for a
2682  * column constraint and "tab_check" for a table constraint. We
2683  * no longer have any info about the syntactic positioning of the
2684  * constraint phrase, so we approximate this by seeing whether the
2685  * expression references more than one column. (If the user
2686  * played by the rules, the result is the same...)
2687  *
2688  * Note: pull_var_clause() doesn't descend into sublinks, but we
2689  * eliminated those above; and anyway this only needs to be an
2690  * approximate answer.
2691  */
2692  List *vars;
2693  char *colname;
2694 
2695  vars = pull_var_clause(expr, 0);
2696 
2697  /* eliminate duplicates */
2698  vars = list_union(NIL, vars);
2699 
2700  if (list_length(vars) == 1)
2701  colname = get_attname(RelationGetRelid(rel),
2702  ((Var *) linitial(vars))->varattno,
2703  true);
2704  else
2705  colname = NULL;
2706 
2708  colname,
2709  "check",
2710  RelationGetNamespace(rel),
2711  checknames);
2712 
2713  /* save name for future checks */
2714  checknames = lappend(checknames, ccname);
2715  }
2716 
2717  /*
2718  * OK, store it.
2719  */
2720  constrOid =
2721  StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
2722  is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
2723 
2724  numchecks++;
2725 
2726  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2727  cooked->contype = CONSTR_CHECK;
2728  cooked->conoid = constrOid;
2729  cooked->name = ccname;
2730  cooked->attnum = 0;
2731  cooked->expr = expr;
2732  cooked->skip_validation = cdef->skip_validation;
2733  cooked->is_local = is_local;
2734  cooked->inhcount = is_local ? 0 : 1;
2735  cooked->is_no_inherit = cdef->is_no_inherit;
2736  cookedConstraints = lappend(cookedConstraints, cooked);
2737  }
2738 
2739  /*
2740  * Update the count of constraints in the relation's pg_class tuple. We do
2741  * this even if there was no change, in order to ensure that an SI update
2742  * message is sent out for the pg_class tuple, which will force other
2743  * backends to rebuild their relcache entries for the rel. (This is
2744  * critical if we added defaults but not constraints.)
2745  */
2746  SetRelationNumChecks(rel, numchecks);
2747 
2748  return cookedConstraints;
2749 }
#define NIL
Definition: pg_list.h:65
char * ChooseConstraintName(const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2912
bool is_no_inherit
Definition: heap.h:45
AttrNumber attnum
Definition: heap.h:29
#define RelationGetDescr(relation)
Definition: rel.h:482
#define castNode(_type_, nodeptr)
Definition: nodes.h:598
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Node * raw_expr
Definition: parsenodes.h:2162
static Node * cookConstraint(ParseState *pstate, Node *raw_constraint, char *relname)
Definition: heap.c:3070
#define AccessShareLock
Definition: lockdefs.h:36
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:529
int errcode(int sqlerrcode)
Definition: elog.c:610
void * stringToNode(const char *str)
Definition: read.c:89
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname, char attgenerated)
Definition: heap.c:2995
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
List * list_union(const List *list1, const List *list2)
Definition: list.c:915
char * conname
Definition: parsenodes.h:2155
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:726
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:181
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:43
AttrNumber attnum
Definition: heap.h:40
#define linitial(l)
Definition: pg_list.h:195
#define ERROR
Definition: elog.h:43
bool missingMode
Definition: heap.h:31
int inhcount
Definition: heap.h:44
TupleConstr * constr
Definition: tupdesc.h:85
char generated
Definition: heap.h:32
#define RelationGetRelationName(relation)
Definition: rel.h:490
Node * raw_default
Definition: heap.h:30
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
bool skip_validation
Definition: heap.h:42
const char * p_sourcetext
Definition: parse_node.h:179
ConstrType contype
Definition: heap.h:37
List * lappend(List *list, void *datum)
Definition: list.c:321
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal, bool add_column_mode)
Definition: heap.c:2149
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:2762
TupleDesc rd_att
Definition: rel.h:110
uint16 num_check
Definition: tupdesc.h:43
bool is_no_inherit
Definition: parsenodes.h:2161
bool initially_valid
Definition: parsenodes.h:2198
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
Oid conoid
Definition: heap.h:38
#define NameStr(name)
Definition: c.h:615
ConstrType contype
Definition: parsenodes.h:2152
Node * expr
Definition: heap.h:41
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
char * cooked_expr
Definition: parsenodes.h:2163
Definition: regcomp.c:224
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
Definition: pg_list.h:50
bool skip_validation
Definition: parsenodes.h:2197
char * name
Definition: heap.h:39
#define RelationGetRelid(relation)
Definition: rel.h:456
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:2334
bool is_local
Definition: heap.h:43
#define RelationGetNamespace(relation)
Definition: rel.h:497

◆ check_nested_generated()

static void check_nested_generated ( ParseState pstate,
Node node 
)
static

Definition at line 2977 of file heap.c.

References check_nested_generated_walker().

Referenced by cookDefault().

2978 {
2979  check_nested_generated_walker(node, pstate);
2980 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:2946

◆ check_nested_generated_walker()

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

Definition at line 2946 of file heap.c.

References attnum, AttributeNumberIsValid, 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().

2947 {
2948  ParseState *pstate = context;
2949 
2950  if (node == NULL)
2951  return false;
2952  else if (IsA(node, Var))
2953  {
2954  Var *var = (Var *) node;
2955  Oid relid;
2957 
2958  relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
2959  attnum = var->varattno;
2960 
2961  if (OidIsValid(relid) && AttributeNumberIsValid(attnum) && get_attgenerated(relid, attnum))
2962  ereport(ERROR,
2963  (errcode(ERRCODE_SYNTAX_ERROR),
2964  errmsg("cannot use generated column \"%s\" in column generation expression",
2965  get_attname(relid, attnum, false)),
2966  errdetail("A generated column cannot reference another generated column."),
2967  parser_errposition(pstate, var->location)));
2968 
2969  return false;
2970  }
2971  else
2973  (void *) context);
2974 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:2946
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
int errcode(int sqlerrcode)
Definition: elog.c:610
AttrNumber varattno
Definition: primnodes.h:186
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:181
#define OidIsValid(objectId)
Definition: c.h:644
#define ERROR
Definition: elog.h:43
int location
Definition: primnodes.h:196
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:886
Index varno
Definition: primnodes.h:184
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
int16 attnum
Definition: pg_attribute.h:79
#define ereport(elevel,...)
Definition: elog.h:144
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1839
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
int errmsg(const char *fmt,...)
Definition: elog.c:824
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
int16 AttrNumber
Definition: attnum.h:21
List * p_rtable
Definition: parse_node.h:180

◆ CheckAttributeNamesTypes()

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

Definition at line 489 of file heap.c.

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

Referenced by addRangeTableEntryForFunction(), and heap_create_with_catalog().

491 {
492  int i;
493  int j;
494  int natts = tupdesc->natts;
495 
496  /* Sanity check on column count */
497  if (natts < 0 || natts > MaxHeapAttributeNumber)
498  ereport(ERROR,
499  (errcode(ERRCODE_TOO_MANY_COLUMNS),
500  errmsg("tables can have at most %d columns",
501  MaxHeapAttributeNumber)));
502 
503  /*
504  * first check for collision with system attribute names
505  *
506  * Skip this for a view or type relation, since those don't have system
507  * attributes.
508  */
509  if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
510  {
511  for (i = 0; i < natts; i++)
512  {
513  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
514 
515  if (SystemAttributeByName(NameStr(attr->attname)) != NULL)
516  ereport(ERROR,
517  (errcode(ERRCODE_DUPLICATE_COLUMN),
518  errmsg("column name \"%s\" conflicts with a system column name",
519  NameStr(attr->attname))));
520  }
521  }
522 
523  /*
524  * next check for repeated attribute names
525  */
526  for (i = 1; i < natts; i++)
527  {
528  for (j = 0; j < i; j++)
529  {
530  if (strcmp(NameStr(TupleDescAttr(tupdesc, j)->attname),
531  NameStr(TupleDescAttr(tupdesc, i)->attname)) == 0)
532  ereport(ERROR,
533  (errcode(ERRCODE_DUPLICATE_COLUMN),
534  errmsg("column name \"%s\" specified more than once",
535  NameStr(TupleDescAttr(tupdesc, j)->attname))));
536  }
537  }
538 
539  /*
540  * next check the attribute types
541  */
542  for (i = 0; i < natts; i++)
543  {
545  TupleDescAttr(tupdesc, i)->atttypid,
546  TupleDescAttr(tupdesc, i)->attcollation,
547  NIL, /* assume we're creating a new rowtype */
548  flags);
549  }
550 }
#define NIL
Definition: pg_list.h:65
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
int errcode(int sqlerrcode)
Definition: elog.c:610
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
Oid attcollation
Definition: pg_attribute.h:157
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
Definition: heap.c:261
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
Oid atttypid
Definition: pg_attribute.h:49
#define ereport(elevel,...)
Definition: elog.h:144
#define MaxHeapAttributeNumber
Definition: htup_details.h:47
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
#define NameStr(name)
Definition: c.h:615
void CheckAttributeType(const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
Definition: heap.c:581

◆ CheckAttributeType()

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

Definition at line 581 of file heap.c.

References AccessShareLock, CheckAttributeType(), 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(), CheckAttributeType(), ComputePartitionAttrs(), and ConstructTupleDescriptor().

585 {
586  char att_typtype = get_typtype(atttypid);
587  Oid att_typelem;
588 
589  if (att_typtype == TYPTYPE_PSEUDO)
590  {
591  /*
592  * We disallow pseudo-type columns, with the exception of ANYARRAY,
593  * RECORD, and RECORD[] when the caller says that those are OK.
594  *
595  * We don't need to worry about recursive containment for RECORD and
596  * RECORD[] because (a) no named composite type should be allowed to
597  * contain those, and (b) two "anonymous" record types couldn't be
598  * considered to be the same type, so infinite recursion isn't
599  * possible.
600  */
601  if (!((atttypid == ANYARRAYOID && (flags & CHKATYPE_ANYARRAY)) ||
602  (atttypid == RECORDOID && (flags & CHKATYPE_ANYRECORD)) ||
603  (atttypid == RECORDARRAYOID && (flags & CHKATYPE_ANYRECORD))))
604  {
605  if (flags & CHKATYPE_IS_PARTKEY)
606  ereport(ERROR,
607  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
608  /* translator: first %s is an integer not a name */
609  errmsg("partition key column %s has pseudo-type %s",
611  else
612  ereport(ERROR,
613  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
614  errmsg("column \"%s\" has pseudo-type %s",
616  }
617  }
618  else if (att_typtype == TYPTYPE_DOMAIN)
619  {
620  /*
621  * If it's a domain, recurse to check its base type.
622  */
624  containing_rowtypes,
625  flags);
626  }
627  else if (att_typtype == TYPTYPE_COMPOSITE)
628  {
629  /*
630  * For a composite type, recurse into its attributes.
631  */
632  Relation relation;
633  TupleDesc tupdesc;
634  int i;
635 
636  /*
637  * Check for self-containment. Eventually we might be able to allow
638  * this (just return without complaint, if so) but it's not clear how
639  * many other places would require anti-recursion defenses before it
640  * would be safe to allow tables to contain their own rowtype.
641  */
642  if (list_member_oid(containing_rowtypes, atttypid))
643  ereport(ERROR,
644  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
645  errmsg("composite type %s cannot be made a member of itself",
647 
648  containing_rowtypes = lappend_oid(containing_rowtypes, atttypid);
649 
651 
652  tupdesc = RelationGetDescr(relation);
653 
654  for (i = 0; i < tupdesc->natts; i++)
655  {
656  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
657 
658  if (attr->attisdropped)
659  continue;
660  CheckAttributeType(NameStr(attr->attname),
661  attr->atttypid, attr->attcollation,
662  containing_rowtypes,
663  flags & ~CHKATYPE_IS_PARTKEY);
664  }
665 
666  relation_close(relation, AccessShareLock);
667 
668  containing_rowtypes = list_delete_last(containing_rowtypes);
669  }
670  else if (att_typtype == TYPTYPE_RANGE)
671  {
672  /*
673  * If it's a range, recurse to check its subtype.
674  */
677  containing_rowtypes,
678  flags);
679  }
680  else if (OidIsValid((att_typelem = get_element_type(atttypid))))
681  {
682  /*
683  * Must recurse into array types, too, in case they are composite.
684  */
686  containing_rowtypes,
687  flags);
688  }
689 
690  /*
691  * This might not be strictly invalid per SQL standard, but it is pretty
692  * useless, and it cannot be dumped, so we must disallow it.
693  */
695  {
696  if (flags & CHKATYPE_IS_PARTKEY)
697  ereport(ERROR,
698  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
699  /* translator: first %s is an integer not a name */
700  errmsg("no collation was derived for partition key column %s with collatable type %s",
702  errhint("Use the COLLATE clause to set the collation explicitly.")));
703  else
704  ereport(ERROR,
705  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
706  errmsg("no collation was derived for column \"%s\" with collatable type %s",
708  errhint("Use the COLLATE clause to set the collation explicitly.")));
709  }
710 }
int errhint(const char *fmt,...)
Definition: elog.c:1071
#define RelationGetDescr(relation)
Definition: rel.h:482
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2636
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:610
char get_typtype(Oid typid)
Definition: lsyscache.c:2517
char * format_type_be(Oid type_oid)
Definition: format_type.c:327
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define OidIsValid(objectId)
Definition: c.h:644
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2609
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
Oid attcollation
Definition: pg_attribute.h:157
List * list_delete_last(List *list)
Definition: list.c:877
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
Oid atttypid
Definition: pg_attribute.h:49
Oid get_range_collation(Oid rangeOid)
Definition: lsyscache.c:3258
#define ereport(elevel,...)
Definition: elog.h:144
#define CHKATYPE_IS_PARTKEY
Definition: heap.h:25
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:674
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define CHKATYPE_ANYRECORD
Definition: heap.h:24
#define CHKATYPE_ANYARRAY
Definition: heap.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
#define NameStr(name)
Definition: c.h:615
void CheckAttributeType(const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
Definition: heap.c:581
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2409
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:2958
Oid get_range_subtype(Oid rangeOid)
Definition: lsyscache.c:3232

◆ cookConstraint()

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

Definition at line 3070 of file heap.c.

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

Referenced by AddRelationNewConstraints().

3073 {
3074  Node *expr;
3075 
3076  /*
3077  * Transform raw parsetree to executable expression.
3078  */
3079  expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
3080 
3081  /*
3082  * Make sure it yields a boolean result.
3083  */
3084  expr = coerce_to_boolean(pstate, expr, "CHECK");
3085 
3086  /*
3087  * Take care of collations.
3088  */
3089  assign_expr_collations(pstate, expr);
3090 
3091  /*
3092  * Make sure no outside relations are referred to (this is probably dead
3093  * code now that add_missing_from is history).
3094  */
3095  if (list_length(pstate->p_rtable) != 1)
3096  ereport(ERROR,
3097  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
3098  errmsg("only table \"%s\" can be referenced in check constraint",
3099  relname)));
3100 
3101  return expr;
3102 }
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:145
Definition: nodes.h:529
int errcode(int sqlerrcode)
Definition: elog.c:610
NameData relname
Definition: pg_class.h:38
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
static int list_length(const List *l)
Definition: pg_list.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:824
List * p_rtable
Definition: parse_node.h:180
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)

◆ cookDefault()

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

Definition at line 2995 of file heap.c.

References Assert, assign_expr_collations(), 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().

3001 {
3002  Node *expr;
3003 
3004  Assert(raw_default != NULL);
3005 
3006  /*
3007  * Transform raw parsetree to executable expression.
3008  */
3009  expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
3010 
3011  if (attgenerated)
3012  {
3013  check_nested_generated(pstate, expr);
3014 
3015  if (contain_mutable_functions(expr))
3016  ereport(ERROR,
3017  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3018  errmsg("generation expression is not immutable")));
3019  }
3020  else
3021  {
3022  /*
3023  * For a default expression, transformExpr() should have rejected
3024  * column references.
3025  */
3026  Assert(!contain_var_clause(expr));
3027  }
3028 
3029  /*
3030  * Coerce the expression to the correct type and typmod, if given. This
3031  * should match the parser's processing of non-defaulted expressions ---
3032  * see transformAssignedExpr().
3033  */
3034  if (OidIsValid(atttypid))
3035  {
3036  Oid type_id = exprType(expr);
3037 
3038  expr = coerce_to_target_type(pstate, expr, type_id,
3039  atttypid, atttypmod,
3042  -1);
3043  if (expr == NULL)
3044  ereport(ERROR,
3045  (errcode(ERRCODE_DATATYPE_MISMATCH),
3046  errmsg("column \"%s\" is of type %s"
3047  " but default expression is of type %s",
3048  attname,
3050  format_type_be(type_id)),
3051  errhint("You will need to rewrite or cast the expression.")));
3052  }
3053 
3054  /*
3055  * Finally, take care of collations in the finished expression.
3056  */
3057  assign_expr_collations(pstate, expr);
3058 
3059  return expr;
3060 }
int errhint(const char *fmt,...)
Definition: elog.c:1071
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:145
Definition: nodes.h:529
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:327
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
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:77
Oid atttypid
Definition: pg_attribute.h:49
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:738
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static void check_nested_generated(ParseState *pstate, Node *node)
Definition: heap.c:2977
int errmsg(const char *fmt,...)
Definition: elog.c:824
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:647

◆ DeleteAttributeTuples()

void DeleteAttributeTuples ( Oid  relid)

Definition at line 1529 of file heap.c.

References AttributeRelidNumIndexId, 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().

1530 {
1531  Relation attrel;
1532  SysScanDesc scan;
1533  ScanKeyData key[1];
1534  HeapTuple atttup;
1535 
1536  /* Grab an appropriate lock on the pg_attribute relation */
1537  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1538 
1539  /* Use the index to scan only attributes of the target relation */
1540  ScanKeyInit(&key[0],
1541  Anum_pg_attribute_attrelid,
1542  BTEqualStrategyNumber, F_OIDEQ,
1543  ObjectIdGetDatum(relid));
1544 
1545  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1546  NULL, 1, key);
1547 
1548  /* Delete all the matching tuples */
1549  while ((atttup = systable_getnext(scan)) != NULL)
1550  CatalogTupleDelete(attrel, &atttup->t_self);
1551 
1552  /* Clean up after the scan */
1553  systable_endscan(scan);
1554  table_close(attrel, RowExclusiveLock);
1555 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ DeleteRelationTuple()

void DeleteRelationTuple ( Oid  relid)

Definition at line 1500 of file heap.c.

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

1501 {
1502  Relation pg_class_desc;
1503  HeapTuple tup;
1504 
1505  /* Grab an appropriate lock on the pg_class relation */
1506  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1507 
1508  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1509  if (!HeapTupleIsValid(tup))
1510  elog(ERROR, "cache lookup failed for relation %u", relid);
1511 
1512  /* delete the relation tuple from pg_class, and finish up */
1513  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1514 
1515  ReleaseSysCache(tup);
1516 
1517  table_close(pg_class_desc, RowExclusiveLock);
1518 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

Definition at line 1566 of file heap.c.

References AttributeRelidNumIndexId, 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().

1567 {
1568  Relation attrel;
1569  SysScanDesc scan;
1570  ScanKeyData key[2];
1571  HeapTuple atttup;
1572 
1573  /* Grab an appropriate lock on the pg_attribute relation */
1574  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1575 
1576  /* Use the index to scan only system attributes of the target relation */
1577  ScanKeyInit(&key[0],
1578  Anum_pg_attribute_attrelid,
1579  BTEqualStrategyNumber, F_OIDEQ,
1580  ObjectIdGetDatum(relid));
1581  ScanKeyInit(&key[1],
1582  Anum_pg_attribute_attnum,
1583  BTLessEqualStrategyNumber, F_INT2LE,
1584  Int16GetDatum(0));
1585 
1586  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1587  NULL, 2, key);
1588 
1589  /* Delete all the matching tuples */
1590  while ((atttup = systable_getnext(scan)) != NULL)
1591  CatalogTupleDelete(attrel, &atttup->t_self);
1592 
1593  /* Clean up after the scan */
1594  systable_endscan(scan);
1595  table_close(attrel, RowExclusiveLock);
1596 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define Int16GetDatum(X)
Definition: postgres.h:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ 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 
)

Definition at line 294 of file heap.c.

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

Referenced by heap_create_with_catalog(), and index_create().

308 {
309  bool create_storage;
310  Relation rel;
311 
312  /* The caller must have provided an OID for the relation. */
313  Assert(OidIsValid(relid));
314 
315  /*
316  * Don't allow creating relations in pg_catalog directly, even though it
317  * is allowed to move user defined relations there. Semantics with search
318  * paths including pg_catalog are too confusing for now.
319  *
320  * But allow creating indexes on relations in pg_catalog even if
321  * allow_system_table_mods = off, upper layers already guarantee it's on a
322  * user defined relation, not a system one.
323  */
324  if (!allow_system_table_mods &&
325  ((IsCatalogNamespace(relnamespace) && relkind != RELKIND_INDEX) ||
326  IsToastNamespace(relnamespace)) &&
328  ereport(ERROR,
329  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
330  errmsg("permission denied to create \"%s.%s\"",
331  get_namespace_name(relnamespace), relname),
332  errdetail("System catalog modifications are currently disallowed.")));
333 
334  *relfrozenxid = InvalidTransactionId;
335  *relminmxid = InvalidMultiXactId;
336 
337  /* Handle reltablespace for specific relkinds. */
338  switch (relkind)
339  {
340  case RELKIND_VIEW:
341  case RELKIND_COMPOSITE_TYPE:
342  case RELKIND_FOREIGN_TABLE:
343 
344  /*
345  * Force reltablespace to zero if the relation has no physical
346  * storage. This is mainly just for cleanliness' sake.
347  *
348  * Partitioned tables and indexes don't have physical storage
349  * either, but we want to keep their tablespace settings so that
350  * their children can inherit it.
351  */
352  reltablespace = InvalidOid;
353  break;
354 
355  case RELKIND_SEQUENCE:
356 
357  /*
358  * Force reltablespace to zero for sequences, since we don't
359  * support moving them around into different tablespaces.
360  */
361  reltablespace = InvalidOid;
362  break;
363  default:
364  break;
365  }
366 
367  /*
368  * Decide whether to create storage. If caller passed a valid relfilenode,
369  * storage is already created, so don't do it here. Also don't create it
370  * for relkinds without physical storage.
371  */
372  if (!RELKIND_HAS_STORAGE(relkind) || OidIsValid(relfilenode))
373  create_storage = false;
374  else
375  {
376  create_storage = true;
377  relfilenode = relid;
378  }
379 
380  /*
381  * Never allow a pg_class entry to explicitly specify the database's
382  * default tablespace in reltablespace; force it to zero instead. This
383  * ensures that if the database is cloned with a different default
384  * tablespace, the pg_class entry will still match where CREATE DATABASE
385  * will put the physically copied relation.
386  *
387  * Yes, this is a bit of a hack.
388  */
389  if (reltablespace == MyDatabaseTableSpace)
390  reltablespace = InvalidOid;
391 
392  /*
393  * build the relcache entry.
394  */
396  relnamespace,
397  tupDesc,
398  relid,
399  accessmtd,
400  relfilenode,
401  reltablespace,
402  shared_relation,
403  mapped_relation,
404  relpersistence,
405  relkind);
406 
407  /*
408  * Have the storage manager create the relation's disk file, if needed.
409  *
410  * For relations the callback creates both the main and the init fork, for
411  * indexes only the main fork is created. The other forks will be created
412  * on demand.
413  */
414  if (create_storage)
415  {
416  RelationOpenSmgr(rel);
417 
418  switch (rel->rd_rel->relkind)
419  {
420  case RELKIND_VIEW:
421  case RELKIND_COMPOSITE_TYPE:
422  case RELKIND_FOREIGN_TABLE:
423  case RELKIND_PARTITIONED_TABLE:
424  case RELKIND_PARTITIONED_INDEX:
425  Assert(false);
426  break;
427 
428  case RELKIND_INDEX:
429  case RELKIND_SEQUENCE:
430  RelationCreateStorage(rel->rd_node, relpersistence);
431  break;
432 
433  case RELKIND_RELATION:
434  case RELKIND_TOASTVALUE:
435  case RELKIND_MATVIEW:
437  relpersistence,
438  relfrozenxid, relminmxid);
439  break;
440  }
441  }
442 
443  return rel;
444 }
int errcode(int sqlerrcode)
Definition: elog.c:610
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:195
Form_pg_class rd_rel
Definition: rel.h:109
NameData relname
Definition: pg_class.h:38
#define OidIsValid(objectId)
Definition: c.h:644
Oid MyDatabaseTableSpace
Definition: globals.c:87
#define RelationOpenSmgr(relation)
Definition: rel.h:513
SMgrRelation RelationCreateStorage(RelFileNode rnode, char relpersistence)
Definition: storage.c:118
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3191
#define IsNormalProcessingMode()
Definition: miscadmin.h:394
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define InvalidTransactionId
Definition: transam.h:31
#define InvalidMultiXactId
Definition: multixact.h:23
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
RelFileNode rd_node
Definition: rel.h:55
#define Assert(condition)
Definition: c.h:738
static void table_relation_set_new_filenode(Relation rel, const RelFileNode *newrnode, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition: tableam.h:1371
bool IsCatalogNamespace(Oid namespaceId)
Definition: catalog.c:177
int errmsg(const char *fmt,...)
Definition: elog.c:824
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:3335

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

References AddNewAttributeTuples(), AddNewRelationTuple(), AddNewRelationType(), Assert, AssignTypeArrayOid(), binary_upgrade_next_heap_pg_class_oid, binary_upgrade_next_toast_pg_class_oid, CheckAttributeNamesTypes(), CHKATYPE_ANYARRAY, ObjectAddress::classId, CStringGetDatum, DEFAULT_TYPDELIM, DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg(), ERROR, get_relname_relid(), get_user_default_acl(), GetNewRelFileNode(), GetSysCacheOid2, heap_create(), InvalidOid, InvokeObjectPostCreateHookArg, IsBinaryUpgrade, IsBootstrapProcessingMode, IsNormalProcessingMode, IsUnderPostmaster, makeArrayTypeName(), moveArrayTypeName(), NoLock, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, ONCOMMIT_NOOP, pfree(), PointerGetDatum, RelationData::rd_att, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnNewAcl(), recordDependencyOnOwner(), register_on_commit_action(), RelationGetRelid, RowExclusiveLock, StoreConstraints(), table_close(), table_open(), TypeCreate(), and TYPENAMENSP.

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

1114 {
1115  Relation pg_class_desc;
1116  Relation new_rel_desc;
1117  Acl *relacl;
1118  Oid existing_relid;
1119  Oid old_type_oid;
1120  Oid new_type_oid;
1121  ObjectAddress new_type_addr;
1122  Oid new_array_oid = InvalidOid;
1123  TransactionId relfrozenxid;
1124  MultiXactId relminmxid;
1125 
1126  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1127 
1128  /*
1129  * sanity checks
1130  */
1132 
1133  /*
1134  * Validate proposed tupdesc for the desired relkind. If
1135  * allow_system_table_mods is on, allow ANYARRAY to be used; this is a
1136  * hack to allow creating pg_statistic and cloning it during VACUUM FULL.
1137  */
1138  CheckAttributeNamesTypes(tupdesc, relkind,
1139  allow_system_table_mods ? CHKATYPE_ANYARRAY : 0);
1140 
1141  /*
1142  * This would fail later on anyway, if the relation already exists. But
1143  * by catching it here we can emit a nicer error message.
1144  */
1145  existing_relid = get_relname_relid(relname, relnamespace);
1146  if (existing_relid != InvalidOid)
1147  ereport(ERROR,
1148  (errcode(ERRCODE_DUPLICATE_TABLE),
1149  errmsg("relation \"%s\" already exists", relname)));
1150 
1151  /*
1152  * Since we are going to create a rowtype as well, also check for
1153  * collision with an existing type name. If there is one and it's an
1154  * autogenerated array, we can rename it out of the way; otherwise we can
1155  * at least give a good error message.
1156  */
1157  old_type_oid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
1159  ObjectIdGetDatum(relnamespace));
1160  if (OidIsValid(old_type_oid))
1161  {
1162  if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
1163  ereport(ERROR,
1165  errmsg("type \"%s\" already exists", relname),
1166  errhint("A relation has an associated type of the same name, "
1167  "so you must use a name that doesn't conflict "
1168  "with any existing type.")));
1169  }
1170 
1171  /*
1172  * Shared relations must be in pg_global (last-ditch check)
1173  */
1174  if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
1175  elog(ERROR, "shared relations must be placed in pg_global tablespace");
1176 
1177  /*
1178  * Allocate an OID for the relation, unless we were told what to use.
1179  *
1180  * The OID will be the relfilenode as well, so make sure it doesn't
1181  * collide with either pg_class OIDs or existing physical files.
1182  */
1183  if (!OidIsValid(relid))
1184  {
1185  /* Use binary-upgrade override for pg_class.oid/relfilenode? */
1186  if (IsBinaryUpgrade &&
1187  (relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
1188  relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
1189  relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE ||
1190  relkind == RELKIND_PARTITIONED_TABLE))
1191  {
1193  ereport(ERROR,
1194  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1195  errmsg("pg_class heap OID value not set when in binary upgrade mode")));
1196 
1199  }
1200  /* There might be no TOAST table, so we have to test for it. */
1201  else if (IsBinaryUpgrade &&
1203  relkind == RELKIND_TOASTVALUE)
1204  {
1207  }
1208  else
1209  relid = GetNewRelFileNode(reltablespace, pg_class_desc,
1210  relpersistence);
1211  }
1212 
1213  /*
1214  * Determine the relation's initial permissions.
1215  */
1216  if (use_user_acl)
1217  {
1218  switch (relkind)
1219  {
1220  case RELKIND_RELATION:
1221  case RELKIND_VIEW:
1222  case RELKIND_MATVIEW:
1223  case RELKIND_FOREIGN_TABLE:
1224  case RELKIND_PARTITIONED_TABLE:
1225  relacl = get_user_default_acl(OBJECT_TABLE, ownerid,
1226  relnamespace);
1227  break;
1228  case RELKIND_SEQUENCE:
1229  relacl = get_user_default_acl(OBJECT_SEQUENCE, ownerid,
1230  relnamespace);
1231  break;
1232  default:
1233  relacl = NULL;
1234  break;
1235  }
1236  }
1237  else
1238  relacl = NULL;
1239 
1240  /*
1241  * Create the relcache entry (mostly dummy at this point) and the physical
1242  * disk file. (If we fail further down, it's the smgr's responsibility to
1243  * remove the disk file again.)
1244  */
1245  new_rel_desc = heap_create(relname,
1246  relnamespace,
1247  reltablespace,
1248  relid,
1249  InvalidOid,
1250  accessmtd,
1251  tupdesc,
1252  relkind,
1253  relpersistence,
1254  shared_relation,
1255  mapped_relation,
1256  allow_system_table_mods,
1257  &relfrozenxid,
1258  &relminmxid);
1259 
1260  Assert(relid == RelationGetRelid(new_rel_desc));
1261 
1262  new_rel_desc->rd_rel->relrewrite = relrewrite;
1263 
1264  /*
1265  * Decide whether to create an array type over the relation's rowtype. We
1266  * do not create any array types for system catalogs (ie, those made
1267  * during initdb). We do not create them where the use of a relation as
1268  * such is an implementation detail: toast tables, sequences and indexes.
1269  */
1270  if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
1271  relkind == RELKIND_VIEW ||
1272  relkind == RELKIND_MATVIEW ||
1273  relkind == RELKIND_FOREIGN_TABLE ||
1274  relkind == RELKIND_COMPOSITE_TYPE ||
1275  relkind == RELKIND_PARTITIONED_TABLE))
1276  new_array_oid = AssignTypeArrayOid();
1277 
1278  /*
1279  * Since defining a relation also defines a complex type, we add a new
1280  * system type corresponding to the new relation. The OID of the type can
1281  * be preselected by the caller, but if reltypeid is InvalidOid, we'll
1282  * generate a new OID for it.
1283  *
1284  * NOTE: we could get a unique-index failure here, in case someone else is
1285  * creating the same type name in parallel but hadn't committed yet when
1286  * we checked for a duplicate name above.
1287  */
1288  new_type_addr = AddNewRelationType(relname,
1289  relnamespace,
1290  relid,
1291  relkind,
1292  ownerid,
1293  reltypeid,
1294  new_array_oid);
1295  new_type_oid = new_type_addr.objectId;
1296  if (typaddress)
1297  *typaddress = new_type_addr;
1298 
1299  /*
1300  * Now make the array type if wanted.
1301  */
1302  if (OidIsValid(new_array_oid))
1303  {
1304  char *relarrayname;
1305 
1306  relarrayname = makeArrayTypeName(relname, relnamespace);
1307 
1308  TypeCreate(new_array_oid, /* force the type's OID to this */
1309  relarrayname, /* Array type name */
1310  relnamespace, /* Same namespace as parent */
1311  InvalidOid, /* Not composite, no relationOid */
1312  0, /* relkind, also N/A here */
1313  ownerid, /* owner's ID */
1314  -1, /* Internal size (varlena) */
1315  TYPTYPE_BASE, /* Not composite - typelem is */
1316  TYPCATEGORY_ARRAY, /* type-category (array) */
1317  false, /* array types are never preferred */
1318  DEFAULT_TYPDELIM, /* default array delimiter */
1319  F_ARRAY_IN, /* array input proc */
1320  F_ARRAY_OUT, /* array output proc */
1321  F_ARRAY_RECV, /* array recv (bin) proc */
1322  F_ARRAY_SEND, /* array send (bin) proc */
1323  InvalidOid, /* typmodin procedure - none */
1324  InvalidOid, /* typmodout procedure - none */
1325  F_ARRAY_TYPANALYZE, /* array analyze procedure */
1326  new_type_oid, /* array element type - the rowtype */
1327  true, /* yes, this is an array type */
1328  InvalidOid, /* this has no array type */
1329  InvalidOid, /* domain base type - irrelevant */
1330  NULL, /* default value - none */
1331  NULL, /* default binary representation */
1332  false, /* passed by reference */
1333  TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1334  TYPSTORAGE_EXTENDED, /* fully TOASTable */
1335  -1, /* typmod */
1336  0, /* array dimensions for typBaseType */
1337  false, /* Type NOT NULL */
1338  InvalidOid); /* rowtypes never have a collation */
1339 
1340  pfree(relarrayname);
1341  }
1342 
1343  /*
1344  * now create an entry in pg_class for the relation.
1345  *
1346  * NOTE: we could get a unique-index failure here, in case someone else is
1347  * creating the same relation name in parallel but hadn't committed yet
1348  * when we checked for a duplicate name above.
1349  */
1350  AddNewRelationTuple(pg_class_desc,
1351  new_rel_desc,
1352  relid,
1353  new_type_oid,
1354  reloftypeid,
1355  ownerid,
1356  relkind,
1357  relfrozenxid,
1358  relminmxid,
1359  PointerGetDatum(relacl),
1360  reloptions);
1361 
1362  /*
1363  * now add tuples to pg_attribute for the attributes in our new relation.
1364  */
1365  AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind);
1366 
1367  /*
1368  * Make a dependency link to force the relation to be deleted if its
1369  * namespace is. Also make a dependency link to its owner, as well as
1370  * dependencies for any roles mentioned in the default ACL.
1371  *
1372  * For composite types, these dependencies are tracked for the pg_type
1373  * entry, so we needn't record them here. Likewise, TOAST tables don't
1374  * need a namespace dependency (they live in a pinned namespace) nor an
1375  * owner dependency (they depend indirectly through the parent table), nor
1376  * should they have any ACL entries. The same applies for extension
1377  * dependencies.
1378  *
1379  * Also, skip this in bootstrap mode, since we don't make dependencies
1380  * while bootstrapping.
1381  */
1382  if (relkind != RELKIND_COMPOSITE_TYPE &&
1383  relkind != RELKIND_TOASTVALUE &&
1385  {
1386  ObjectAddress myself,
1387  referenced;
1388 
1389  myself.classId = RelationRelationId;
1390  myself.objectId = relid;
1391  myself.objectSubId = 0;
1392 
1393  referenced.classId = NamespaceRelationId;
1394  referenced.objectId = relnamespace;
1395  referenced.objectSubId = 0;
1396  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1397 
1398  recordDependencyOnOwner(RelationRelationId, relid, ownerid);
1399 
1400  recordDependencyOnNewAcl(RelationRelationId, relid, 0, ownerid, relacl);
1401 
1402  recordDependencyOnCurrentExtension(&myself, false);
1403 
1404  if (reloftypeid)
1405  {
1406  referenced.classId = TypeRelationId;
1407  referenced.objectId = reloftypeid;
1408  referenced.objectSubId = 0;
1409  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1410  }
1411 
1412  /*
1413  * Make a dependency link to force the relation to be deleted if its
1414  * access method is. Do this only for relation and materialized views.
1415  *
1416  * No need to add an explicit dependency for the toast table, as the
1417  * main table depends on it.
1418  */
1419  if (relkind == RELKIND_RELATION ||
1420  relkind == RELKIND_MATVIEW)
1421  {
1422  referenced.classId = AccessMethodRelationId;
1423  referenced.objectId = accessmtd;
1424  referenced.objectSubId = 0;
1425  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1426  }
1427  }
1428 
1429  /* Post creation hook for new relation */
1430  InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
1431 
1432  /*
1433  * Store any supplied constraints and defaults.
1434  *
1435  * NB: this may do a CommandCounterIncrement and rebuild the relcache
1436  * entry, so the relation must be valid and self-consistent at this point.
1437  * In particular, there are not yet constraints and defaults anywhere.
1438  */
1439  StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
1440 
1441  /*
1442  * If there's a special on-commit action, remember it
1443  */
1444  if (oncommit != ONCOMMIT_NOOP)
1445  register_on_commit_action(relid, oncommit);
1446 
1447  /*
1448  * ok, the relation has been cataloged, so close our relations and return
1449  * the OID of the newly created relation.
1450  */
1451  table_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
1452  table_close(pg_class_desc, RowExclusiveLock);
1453 
1454  return relid;
1455 }
void register_on_commit_action(Oid relid, OnCommitAction action)
Definition: tablecmds.c:15237
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:785
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
int errhint(const char *fmt,...)
Definition: elog.c:1071
Oid binary_upgrade_next_heap_pg_class_oid
Definition: heap.c:92
uint32 TransactionId
Definition: c.h:513
Oid binary_upgrade_next_toast_pg_class_oid
Definition: heap.c:93
static void AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc, char relkind)
Definition: heap.c:787
#define PointerGetDatum(X)
Definition: postgres.h:556
int errcode(int sqlerrcode)
Definition: elog.c:610
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:164
Form_pg_class rd_rel
Definition: rel.h:109
NameData relname
Definition: pg_class.h:38
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
bool IsBinaryUpgrade
Definition: globals.c:110
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1797
#define NoLock
Definition: lockdefs.h:34
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:846
#define IsNormalProcessingMode()
Definition: miscadmin.h:394
bool IsUnderPostmaster
Definition: globals.c:109
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
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:1018
static void StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
Definition: heap.c:2442
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:153
TupleDesc rd_att
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
TransactionId MultiXactId
Definition: c.h:523
#define Assert(condition)
Definition: c.h:738
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:138
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:194
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)
Definition: heap.c:294
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:380
Oid AssignTypeArrayOid(void)
Definition: typecmds.c:2021
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition: aclchk.c:5466
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:392
#define CHKATYPE_ANYARRAY
Definition: heap.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:824
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 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:192
#define elog(elevel,...)
Definition: elog.h:214
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:949
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, int flags)
Definition: heap.c:489
#define RelationGetRelid(relation)
Definition: rel.h:456
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:5390

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

Definition at line 1848 of file heap.c.

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

1849 {
1850  Relation rel;
1851  HeapTuple tuple;
1852  Oid parentOid = InvalidOid,
1853  defaultPartOid = InvalidOid;
1854 
1855  /*
1856  * To drop a partition safely, we must grab exclusive lock on its parent,
1857  * because another backend might be about to execute a query on the parent
1858  * table. If it relies on previously cached partition descriptor, then it
1859  * could attempt to access the just-dropped relation as its partition. We
1860  * must therefore take a table lock strong enough to prevent all queries
1861  * on the table from proceeding until we commit and send out a
1862  * shared-cache-inval notice that will make them update their partition
1863  * descriptors.
1864  */
1865  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1866  if (!HeapTupleIsValid(tuple))
1867  elog(ERROR, "cache lookup failed for relation %u", relid);
1868  if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
1869  {
1870  parentOid = get_partition_parent(relid);
1872 
1873  /*
1874  * If this is not the default partition, dropping it will change the
1875  * default partition's partition constraint, so we must lock it.
1876  */
1877  defaultPartOid = get_default_partition_oid(parentOid);
1878  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1879  LockRelationOid(defaultPartOid, AccessExclusiveLock);
1880  }
1881 
1882  ReleaseSysCache(tuple);
1883 
1884  /*
1885  * Open and lock the relation.
1886  */
1887  rel = relation_open(relid, AccessExclusiveLock);
1888 
1889  /*
1890  * There can no longer be anyone *else* touching the relation, but we
1891  * might still have open queries or cursors, or pending trigger events, in
1892  * our own session.
1893  */
1894  CheckTableNotInUse(rel, "DROP TABLE");
1895 
1896  /*
1897  * This effectively deletes all rows in the table, and may be done in a
1898  * serializable transaction. In that case we must record a rw-conflict in
1899  * to this transaction from each transaction holding a predicate lock on
1900  * the table.
1901  */
1903 
1904  /*
1905  * Delete pg_foreign_table tuple first.
1906  */
1907  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1908  {
1909  Relation rel;
1910  HeapTuple tuple;
1911 
1912  rel = table_open(ForeignTableRelationId, RowExclusiveLock);
1913 
1915  if (!HeapTupleIsValid(tuple))
1916  elog(ERROR, "cache lookup failed for foreign table %u", relid);
1917 
1918  CatalogTupleDelete(rel, &tuple->t_self);
1919 
1920  ReleaseSysCache(tuple);
1922  }
1923 
1924  /*
1925  * If a partitioned table, delete the pg_partitioned_table tuple.
1926  */
1927  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1929 
1930  /*
1931  * If the relation being dropped is the default partition itself,
1932  * invalidate its entry in pg_partitioned_table.
1933  */
1934  if (relid == defaultPartOid)
1936 
1937  /*
1938  * Schedule unlinking of the relation's physical files at commit.
1939  */
1940  if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
1941  RelationDropStorage(rel);
1942 
1943  /*
1944  * Close relcache entry, but *keep* AccessExclusiveLock on the relation
1945  * until transaction commit. This ensures no one else will try to do
1946  * something with the doomed relation.
1947  */
1948  relation_close(rel, NoLock);
1949 
1950  /*
1951  * Remove any associated relation synchronization states.
1952  */
1954 
1955  /*
1956  * Forget any ON COMMIT action for the rel
1957  */
1958  remove_on_commit_action(relid);
1959 
1960  /*
1961  * Flush the relation from the relcache. We want to do this before
1962  * starting to remove catalog entries, just to be certain that no relcache
1963  * entry rebuild will happen partway through. (That should not really
1964  * matter, since we don't do CommandCounterIncrement here, but let's be
1965  * safe.)
1966  */
1967  RelationForgetRelation(relid);
1968 
1969  /*
1970  * remove inheritance information
1971  */
1973 
1974  /*
1975  * delete statistics
1976  */
1977  RemoveStatistics(relid, 0);
1978 
1979  /*
1980  * delete attribute tuples
1981  */
1982  DeleteAttributeTuples(relid);
1983 
1984  /*
1985  * delete relation tuple
1986  */
1987  DeleteRelationTuple(relid);
1988 
1989  if (OidIsValid(parentOid))
1990  {
1991  /*
1992  * If this is not the default partition, the partition constraint of
1993  * the default partition has changed to include the portion of the key
1994  * space previously covered by the dropped partition.
1995  */
1996  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1997  CacheInvalidateRelcacheByRelid(defaultPartOid);
1998 
1999  /*
2000  * Invalidate the parent's relcache so that the partition is no longer
2001  * included in its partition descriptor.
2002  */
2003  CacheInvalidateRelcacheByRelid(parentOid);
2004  /* keep the lock */
2005  }
2006 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void RemoveSubscriptionRel(Oid subid, Oid relid)
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:315
void remove_on_commit_action(Oid relid)
Definition: tablecmds.c:15273
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2736
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
Oid get_partition_parent(Oid relid)
Definition: partition.c:50
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1329
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3533
Oid get_default_partition_oid(Oid parentId)
Definition: partition.c:290
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void RelationDropStorage(Relation rel)
Definition: storage.c:195
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define InvalidOid
Definition: postgres_ext.h:36
void DeleteRelationTuple(Oid relid)
Definition: heap.c:1500
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
static void RelationRemoveInheritance(Oid relid)
Definition: heap.c:1467
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4460
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1529
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:3112
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define AccessExclusiveLock
Definition: lockdefs.h:45
void RemovePartitionKeyByRelId(Oid relid)
Definition: heap.c:3647
#define elog(elevel,...)
Definition: elog.h:214
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:108
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ heap_truncate()

void heap_truncate ( List relids)

Definition at line 3207 of file heap.c.

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

3208 {
3209  List *relations = NIL;
3210  ListCell *cell;
3211 
3212  /* Open relations for processing, and grab exclusive access on each */
3213  foreach(cell, relids)
3214  {
3215  Oid rid = lfirst_oid(cell);
3216  Relation rel;
3217 
3218  rel = table_open(rid, AccessExclusiveLock);
3219  relations = lappend(relations, rel);
3220  }
3221 
3222  /* Don't allow truncate on tables that are referenced by foreign keys */
3223  heap_truncate_check_FKs(relations, true);
3224 
3225  /* OK to do it */
3226  foreach(cell, relations)
3227  {
3228  Relation rel = lfirst(cell);
3229 
3230  /* Truncate the relation */
3231  heap_truncate_one_rel(rel);
3232 
3233  /* Close the relation, but keep exclusive lock on it until commit */
3234  table_close(rel, NoLock);
3235  }
3236 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:3248
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3292
unsigned int Oid
Definition: postgres_ext.h:31
#define NoLock
Definition: lockdefs.h:34
List * lappend(List *list, void *datum)
Definition: list.c:321
#define lfirst(lc)
Definition: pg_list.h:190
#define AccessExclusiveLock
Definition: lockdefs.h:45
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ heap_truncate_check_FKs()

void heap_truncate_check_FKs ( List relations,
bool  tempTables 
)

Definition at line 3292 of file heap.c.

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

3293 {
3294  List *oids = NIL;
3295  List *dependents;
3296  ListCell *cell;
3297 
3298  /*
3299  * Build a list of OIDs of the interesting relations.
3300  *
3301  * If a relation has no triggers, then it can neither have FKs nor be
3302  * referenced by a FK from another table, so we can ignore it. For
3303  * partitioned tables, FKs have no triggers, so we must include them
3304  * anyway.
3305  */
3306  foreach(cell, relations)
3307  {
3308  Relation rel = lfirst(cell);
3309 
3310  if (rel->rd_rel->relhastriggers ||
3311  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3312  oids = lappend_oid(oids, RelationGetRelid(rel));
3313  }
3314 
3315  /*
3316  * Fast path: if no relation has triggers, none has FKs either.
3317  */
3318  if (oids == NIL)
3319  return;
3320 
3321  /*
3322  * Otherwise, must scan pg_constraint. We make one pass with all the
3323  * relations considered; if this finds nothing, then all is well.
3324  */
3325  dependents = heap_truncate_find_FKs(oids);
3326  if (dependents == NIL)
3327  return;
3328 
3329  /*
3330  * Otherwise we repeat the scan once per relation to identify a particular
3331  * pair of relations to complain about. This is pretty slow, but
3332  * performance shouldn't matter much in a failure path. The reason for
3333  * doing things this way is to ensure that the message produced is not
3334  * dependent on chance row locations within pg_constraint.
3335  */
3336  foreach(cell, oids)
3337  {
3338  Oid relid = lfirst_oid(cell);
3339  ListCell *cell2;
3340 
3341  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
3342 
3343  foreach(cell2, dependents)
3344  {
3345  Oid relid2 = lfirst_oid(cell2);
3346 
3347  if (!list_member_oid(oids, relid2))
3348  {
3349  char *relname = get_rel_name(relid);
3350  char *relname2 = get_rel_name(relid2);
3351 
3352  if (tempTables)
3353  ereport(ERROR,
3354  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3355  errmsg("unsupported ON COMMIT and foreign key combination"),
3356  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3357  relname2, relname)));
3358  else
3359  ereport(ERROR,
3360  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3361  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3362  errdetail("Table \"%s\" references \"%s\".",
3363  relname2, relname),
3364  errhint("Truncate table \"%s\" at the same time, "
3365  "or use TRUNCATE ... CASCADE.",
3366  relname2)));
3367  }
3368  }
3369  }
3370 }
#define NIL
Definition: pg_list.h:65
int errhint(const char *fmt,...)
Definition: elog.c:1071
int errcode(int sqlerrcode)
Definition: elog.c:610
Form_pg_class rd_rel
Definition: rel.h:109
NameData relname
Definition: pg_class.h:38
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define list_make1_oid(x1)
Definition: pg_list.h:249
#define ereport(elevel,...)
Definition: elog.h:144
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:674
#define lfirst(lc)
Definition: pg_list.h:190
int errmsg(const char *fmt,...)
Definition: elog.c:824
Definition: pg_list.h:50
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1840
#define RelationGetRelid(relation)
Definition: rel.h:456
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3387
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

Definition at line 3387 of file heap.c.

References AccessShareLock, BTEqualStrategyNumber, ConstraintOidIndexId, 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().

3388 {
3389  List *result = NIL;
3390  List *oids = list_copy(relationIds);
3391  List *parent_cons;
3392  ListCell *cell;
3393  ScanKeyData key;
3394  Relation fkeyRel;
3395  SysScanDesc fkeyScan;
3396  HeapTuple tuple;
3397  bool restart;
3398 
3399  oids = list_copy(relationIds);
3400 
3401  /*
3402  * Must scan pg_constraint. Right now, it is a seqscan because there is
3403  * no available index on confrelid.
3404  */
3405  fkeyRel = table_open(ConstraintRelationId, AccessShareLock);
3406 
3407 restart:
3408  restart = false;
3409  parent_cons = NIL;
3410 
3411  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3412  NULL, 0, NULL);
3413 
3414  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3415  {
3417 
3418  /* Not a foreign key */
3419  if (con->contype != CONSTRAINT_FOREIGN)
3420  continue;
3421 
3422  /* Not referencing one of our list of tables */
3423  if (!list_member_oid(oids, con->confrelid))
3424  continue;
3425 
3426  /*
3427  * If this constraint has a parent constraint which we have not seen
3428  * yet, keep track of it for the second loop, below. Tracking parent
3429  * constraints allows us to climb up to the top-level level constraint
3430  * and look for all possible relations referencing the partitioned
3431  * table.
3432  */
3433  if (OidIsValid(con->conparentid) &&
3434  !list_member_oid(parent_cons, con->conparentid))
3435  parent_cons = lappend_oid(parent_cons, con->conparentid);
3436 
3437  /*
3438  * Add referencer to result, unless present in input list. (Don't
3439  * worry about dupes: we'll fix that below).
3440  */
3441  if (!list_member_oid(relationIds, con->conrelid))
3442  result = lappend_oid(result, con->conrelid);
3443  }
3444 
3445  systable_endscan(fkeyScan);
3446 
3447  /*
3448  * Process each parent constraint we found to add the list of referenced
3449  * relations by them to the oids list. If we do add any new such
3450  * relations, redo the first loop above. Also, if we see that the parent
3451  * constraint in turn has a parent, add that so that we process all
3452  * relations in a single additional pass.
3453  */
3454  foreach(cell, parent_cons)
3455  {
3456  Oid parent = lfirst_oid(cell);
3457 
3458  ScanKeyInit(&key,
3459  Anum_pg_constraint_oid,
3460  BTEqualStrategyNumber, F_OIDEQ,
3461  ObjectIdGetDatum(parent));
3462 
3463  fkeyScan = systable_beginscan(fkeyRel, ConstraintOidIndexId,
3464  true, NULL, 1, &key);
3465 
3466  tuple = systable_getnext(fkeyScan);
3467  if (HeapTupleIsValid(tuple))
3468  {
3470 
3471  /*
3472  * pg_constraint rows always appear for partitioned hierarchies
3473  * this way: on the each side of the constraint, one row appears
3474  * for each partition that points to the top-most table on the
3475  * other side.
3476  *
3477  * Because of this arrangement, we can correctly catch all
3478  * relevant relations by adding to 'parent_cons' all rows with
3479  * valid conparentid, and to the 'oids' list all rows with a zero
3480  * conparentid. If any oids are added to 'oids', redo the first
3481  * loop above by setting 'restart'.
3482  */
3483  if (OidIsValid(con->conparentid))
3484  parent_cons = list_append_unique_oid(parent_cons,
3485  con->conparentid);
3486  else if (!list_member_oid(oids, con->confrelid))
3487  {
3488  oids = lappend_oid(oids, con->confrelid);
3489  restart = true;
3490  }
3491  }
3492 
3493  systable_endscan(fkeyScan);
3494  }
3495 
3496  list_free(parent_cons);
3497  if (restart)
3498  goto restart;
3499 
3500  table_close(fkeyRel, AccessShareLock);
3501  list_free(oids);
3502 
3503  /* Now sort and de-duplicate the result list */
3504  list_sort(result, list_oid_cmp);
3505  list_deduplicate_oid(result);
3506 
3507  return result;
3508 }
#define ConstraintOidIndexId
Definition: indexing.h:132
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
List * list_append_unique_oid(List *list, Oid datum)
Definition: list.c:1217
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define AccessShareLock
Definition: lockdefs.h:36
List * list_copy(const List *oldlist)
Definition: list.c:1403
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define OidIsValid(objectId)
Definition: c.h:644
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1498
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
void list_deduplicate_oid(List *list)
Definition: list.c:1325
#define InvalidOid
Definition: postgres_ext.h:36
FormData_pg_constraint * Form_pg_constraint
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:674
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1481
void list_free(List *list)
Definition: list.c:1376
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ heap_truncate_one_rel()

void heap_truncate_one_rel ( Relation  rel)

Definition at line 3248 of file heap.c.

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

Referenced by ExecuteTruncateGuts(), and heap_truncate().

3249 {
3250  Oid toastrelid;
3251 
3252  /*
3253  * Truncate the relation. Partitioned tables have no storage, so there is
3254  * nothing to do for them here.
3255  */
3256  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3257  return;
3258 
3259  /* Truncate the underlying relation */
3261 
3262  /* If the relation has indexes, truncate the indexes too */
3264 
3265  /* If there is a toast table, truncate that too */
3266  toastrelid = rel->rd_rel->reltoastrelid;
3267  if (OidIsValid(toastrelid))
3268  {
3269  Relation toastrel = table_open(toastrelid, AccessExclusiveLock);
3270 
3272  RelationTruncateIndexes(toastrel);
3273  /* keep the lock... */
3274  table_close(toastrel, NoLock);
3275  }
3276 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
static void table_relation_nontransactional_truncate(Relation rel)
Definition: tableam.h:1388
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:45
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
static void RelationTruncateIndexes(Relation heapRelation)
Definition: heap.c:3159

◆ InsertPgAttributeTuple()

void InsertPgAttributeTuple ( Relation  pg_attribute_rel,
Form_pg_attribute  new_attribute,
Datum  attoptions,
CatalogIndexState  indstate 
)

Definition at line 726 of file heap.c.

References BoolGetDatum, CatalogTupleInsert(), CatalogTupleInsertWithInfo(), CharGetDatum, heap_form_tuple(), heap_freetuple(), Int16GetDatum, Int32GetDatum, NameGetDatum, ObjectIdGetDatum, RelationGetDescr, and values.

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

730 {
731  Datum values[Natts_pg_attribute];
732  bool nulls[Natts_pg_attribute];
733  HeapTuple tup;
734 
735  /* This is a tad tedious, but way cleaner than what we used to do... */
736  memset(values, 0, sizeof(values));
737  memset(nulls, false, sizeof(nulls));
738 
739  values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
740  values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
741  values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
742  values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
743  values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
744  values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
745  values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
746  values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
747  values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
748  values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
749  values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
750  values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
751  values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
752  values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
753  values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(new_attribute->atthasmissing);
754  values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
755  values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(new_attribute->attgenerated);
756  values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
757  values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
758  values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
759  values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
760  values[Anum_pg_attribute_attoptions - 1] = attoptions;
761 
762  /* start out with empty permissions and empty options */
763  nulls[Anum_pg_attribute_attacl - 1] = true;
764  nulls[Anum_pg_attribute_attoptions - 1] = attoptions == (Datum) 0;
765  nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
766  nulls[Anum_pg_attribute_attmissingval - 1] = true;
767 
768  tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
769 
770  /* finally insert the new tuple, update the indexes, and clean up */
771  if (indstate != NULL)
772  CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
773  else
774  CatalogTupleInsert(pg_attribute_rel, tup);
775 
776  heap_freetuple(tup);
777 }
#define NameGetDatum(X)
Definition: postgres.h:595
#define RelationGetDescr(relation)
Definition: rel.h:482
#define Int16GetDatum(X)
Definition: postgres.h:451
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
uintptr_t Datum
Definition: postgres.h:367
void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:204
#define BoolGetDatum(X)
Definition: postgres.h:402
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define Int32GetDatum(X)
Definition: postgres.h:479
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ InsertPgClassTuple()

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

Definition at line 876 of file heap.c.

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

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

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

References Assert, BTEqualStrategyNumber, CatalogTupleUpdate(), ConstraintRelidTypidNameIndexId, 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().

2766 {
2767  bool found;
2768  Relation conDesc;
2769  SysScanDesc conscan;
2770  ScanKeyData skey[3];
2771  HeapTuple tup;
2772 
2773  /* Search for a pg_constraint entry with same name and relation */
2774  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
2775 
2776  found = false;
2777 
2778  ScanKeyInit(&skey[0],
2779  Anum_pg_constraint_conrelid,
2780  BTEqualStrategyNumber, F_OIDEQ,
2782  ScanKeyInit(&skey[1],
2783  Anum_pg_constraint_contypid,
2784  BTEqualStrategyNumber, F_OIDEQ,
2786  ScanKeyInit(&skey[2],
2787  Anum_pg_constraint_conname,
2788  BTEqualStrategyNumber, F_NAMEEQ,
2789  CStringGetDatum(ccname));
2790 
2791  conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId, true,
2792  NULL, 3, skey);
2793 
2794  /* There can be at most one matching row */
2795  if (HeapTupleIsValid(tup = systable_getnext(conscan)))
2796  {
2798 
2799  /* Found it. Conflicts if not identical check constraint */
2800  if (con->contype == CONSTRAINT_CHECK)
2801  {
2802  Datum val;
2803  bool isnull;
2804 
2805  val = fastgetattr(tup,
2806  Anum_pg_constraint_conbin,
2807  conDesc->rd_att, &isnull);
2808  if (isnull)
2809  elog(ERROR, "null conbin for rel %s",
2811  if (equal(expr, stringToNode(TextDatumGetCString(val))))
2812  found = true;
2813  }
2814 
2815  /*
2816  * If the existing constraint is purely inherited (no local
2817  * definition) then interpret addition of a local constraint as a
2818  * legal merge. This allows ALTER ADD CONSTRAINT on parent and child
2819  * tables to be given in either order with same end state. However if
2820  * the relation is a partition, all inherited constraints are always
2821  * non-local, including those that were merged.
2822  */
2823  if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
2824  allow_merge = true;
2825 
2826  if (!found || !allow_merge)
2827  ereport(ERROR,
2829  errmsg("constraint \"%s\" for relation \"%s\" already exists",
2830  ccname, RelationGetRelationName(rel))));
2831 
2832  /* If the child constraint is "no inherit" then cannot merge */
2833  if (con->connoinherit)
2834  ereport(ERROR,
2835  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2836  errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
2837  ccname, RelationGetRelationName(rel))));
2838 
2839  /*
2840  * Must not change an existing inherited constraint to "no inherit"
2841  * status. That's because inherited constraints should be able to
2842  * propagate to lower-level children.
2843  */
2844  if (con->coninhcount > 0 && is_no_inherit)
2845  ereport(ERROR,
2846  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2847  errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
2848  ccname, RelationGetRelationName(rel))));
2849 
2850  /*
2851  * If the child constraint is "not valid" then cannot merge with a
2852  * valid parent constraint.
2853  */
2854  if (is_initially_valid && !con->convalidated)
2855  ereport(ERROR,
2856  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2857  errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
2858  ccname, RelationGetRelationName(rel))));
2859 
2860  /* OK to update the tuple */
2861  ereport(NOTICE,
2862  (errmsg("merging constraint \"%s\" with inherited definition",
2863  ccname)));
2864 
2865  tup = heap_copytuple(tup);
2866  con = (Form_pg_constraint) GETSTRUCT(tup);
2867 
2868  /*
2869  * In case of partitions, an inherited constraint must be inherited
2870  * only once since it cannot have multiple parents and it is never
2871  * considered local.
2872  */
2873  if (rel->rd_rel->relispartition)
2874  {
2875  con->coninhcount = 1;
2876  con->conislocal = false;
2877  }
2878  else
2879  {
2880  if (is_local)
2881  con->conislocal = true;
2882  else
2883  con->coninhcount++;
2884  }
2885 
2886  if (is_no_inherit)
2887  {
2888  Assert(is_local);
2889  con->connoinherit = true;
2890  }
2891 
2892  CatalogTupleUpdate(conDesc, &tup->t_self, tup);
2893  }
2894 
2895  systable_endscan(conscan);
2896  table_close(conDesc, RowExclusiveLock);
2897 
2898  return found;
2899 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3033
int errcode(int sqlerrcode)
Definition: elog.c:610
void * stringToNode(const char *str)
Definition: read.c:89
Form_pg_class rd_rel
Definition: rel.h:109
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define TextDatumGetCString(d)
Definition: builtins.h:88
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
#define NOTICE
Definition: elog.h:37
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ConstraintRelidTypidNameIndexId
Definition: indexing.h:128
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
#define RelationGetRelid(relation)
Definition: rel.h:456
long val
Definition: informix.c:664
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RelationClearMissing()

void RelationClearMissing ( Relation  rel)

Definition at line 2020 of file heap.c.

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

2021 {
2022  Relation attr_rel;
2023  Oid relid = RelationGetRelid(rel);
2024  int natts = RelationGetNumberOfAttributes(rel);
2025  int attnum;
2026  Datum repl_val[Natts_pg_attribute];
2027  bool repl_null[Natts_pg_attribute];
2028  bool repl_repl[Natts_pg_attribute];
2029  Form_pg_attribute attrtuple;
2030  HeapTuple tuple,
2031  newtuple;
2032 
2033  memset(repl_val, 0, sizeof(repl_val));
2034  memset(repl_null, false, sizeof(repl_null));
2035  memset(repl_repl, false, sizeof(repl_repl));
2036 
2037  repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
2038  repl_null[Anum_pg_attribute_attmissingval - 1] = true;
2039 
2040  repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
2041  repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
2042 
2043 
2044  /* Get a lock on pg_attribute */
2045  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
2046 
2047  /* process each non-system attribute, including any dropped columns */
2048  for (attnum = 1; attnum <= natts; attnum++)
2049  {
2050  tuple = SearchSysCache2(ATTNUM,
2051  ObjectIdGetDatum(relid),
2052  Int16GetDatum(attnum));
2053  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
2054  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2055  attnum, relid);
2056 
2057  attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
2058 
2059  /* ignore any where atthasmissing is not true */
2060  if (attrtuple->atthasmissing)
2061  {
2062  newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
2063  repl_val, repl_null, repl_repl);
2064 
2065  CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
2066 
2067  heap_freetuple(newtuple);
2068  }
2069 
2070  ReleaseSysCache(tuple);
2071  }
2072 
2073  /*
2074  * Our update of the pg_attribute rows will force a relcache rebuild, so
2075  * there's nothing else to do here.
2076  */
2077  table_close(attr_rel, RowExclusiveLock);
2078 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:482
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:462
#define Int16GetDatum(X)
Definition: postgres.h:451
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define BoolGetDatum(X)
Definition: postgres.h:402
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1127
#define elog(elevel,...)
Definition: elog.h:214
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ RelationRemoveInheritance()

static void RelationRemoveInheritance ( Oid  relid)
static

Definition at line 1467 of file heap.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), HeapTupleIsValid, InheritsRelidSeqnoIndexId, 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().

1468 {
1469  Relation catalogRelation;
1470  SysScanDesc scan;
1471  ScanKeyData key;
1472  HeapTuple tuple;
1473 
1474  catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
1475 
1476  ScanKeyInit(&key,
1477  Anum_pg_inherits_inhrelid,
1478  BTEqualStrategyNumber, F_OIDEQ,
1479  ObjectIdGetDatum(relid));
1480 
1481  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
1482  NULL, 1, &key);
1483 
1484  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1485  CatalogTupleDelete(catalogRelation, &tuple->t_self);
1486 
1487  systable_endscan(scan);
1488  table_close(catalogRelation, RowExclusiveLock);
1489 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define InheritsRelidSeqnoIndexId
Definition: indexing.h:171
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RelationTruncateIndexes()

static void RelationTruncateIndexes ( Relation  heapRelation)
static

Definition at line 3159 of file heap.c.

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

Referenced by heap_truncate_one_rel().

3160 {
3161  ListCell *indlist;
3162 
3163  /* Ask the relcache to produce a list of the indexes of the rel */
3164  foreach(indlist, RelationGetIndexList(heapRelation))
3165  {
3166  Oid indexId = lfirst_oid(indlist);
3167  Relation currentIndex;
3168  IndexInfo *indexInfo;
3169 
3170  /* Open the index relation; use exclusive lock, just to be sure */
3171  currentIndex = index_open(indexId, AccessExclusiveLock);
3172 
3173  /*
3174  * Fetch info needed for index_build. Since we know there are no
3175  * tuples that actually need indexing, we can use a dummy IndexInfo.
3176  * This is slightly cheaper to build, but the real point is to avoid
3177  * possibly running user-defined code in index expressions or
3178  * predicates. We might be getting invoked during ON COMMIT
3179  * processing, and we don't want to run any such code then.
3180  */
3181  indexInfo = BuildDummyIndexInfo(currentIndex);
3182 
3183  /*
3184  * Now truncate the actual file (and discard buffers).
3185  */
3186  RelationTruncate(currentIndex, 0);
3187 
3188  /* Initialize the index and rebuild */
3189  /* Note: we do not need to re-establish pkey setting */
3190  index_build(heapRelation, currentIndex, indexInfo, true, false);
3191 
3192  /* We're done with this index */
3193  index_close(currentIndex, NoLock);
3194  }
3195 }
unsigned int Oid
Definition: postgres_ext.h:31
#define NoLock
Definition: lockdefs.h:34
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isreindex, bool parallel)
Definition: index.c:2809
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4506
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
#define AccessExclusiveLock
Definition: lockdefs.h:45
IndexInfo * BuildDummyIndexInfo(Relation index)
Definition: index.c:2357
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
#define lfirst_oid(lc)
Definition: pg_list.h:192
void RelationTruncate(Relation rel, BlockNumber nblocks)
Definition: storage.c:277

◆ RemoveAttrDefault()

void RemoveAttrDefault ( Oid  relid,
AttrNumber  attnum,
DropBehavior  behavior,
bool  complain,
bool  internal 
)

Definition at line 1720 of file heap.c.

References AttrDefaultIndexId, BTEqualStrategyNumber, elog, ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum, ObjectAddressStack::object, ObjectIdGetDatum, PERFORM_DELETION_INTERNAL, performDeletion(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ATExecAlterColumnType(), ATExecColumnDefault(), and ATExecDropExpression().

1722 {
1723  Relation attrdef_rel;
1724  ScanKeyData scankeys[2];
1725  SysScanDesc scan;
1726  HeapTuple tuple;
1727  bool found = false;
1728 
1729  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1730 
1731  ScanKeyInit(&scankeys[0],
1732  Anum_pg_attrdef_adrelid,
1733  BTEqualStrategyNumber, F_OIDEQ,
1734  ObjectIdGetDatum(relid));
1735  ScanKeyInit(&scankeys[1],
1736  Anum_pg_attrdef_adnum,
1737  BTEqualStrategyNumber, F_INT2EQ,
1739 
1740  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1741  NULL, 2, scankeys);
1742 
1743  /* There should be at most one matching tuple, but we loop anyway */
1744  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1745  {
1746  ObjectAddress object;
1747  Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
1748 
1749  object.classId = AttrDefaultRelationId;
1750  object.objectId = attrtuple->oid;
1751  object.objectSubId = 0;
1752 
1753  performDeletion(&object, behavior,
1754  internal ? PERFORM_DELETION_INTERNAL : 0);
1755 
1756  found = true;
1757  }
1758 
1759  systable_endscan(scan);
1760  table_close(attrdef_rel, RowExclusiveLock);
1761 
1762  if (complain && !found)
1763  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1764  relid, attnum);
1765 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define Int16GetDatum(X)
Definition: postgres.h:451
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define AttrDefaultIndexId
Definition: indexing.h:89
#define RowExclusiveLock
Definition: lockdefs.h:38
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:312
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:134

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

Definition at line 1775 of file heap.c.

References AccessExclusiveLock, ATTNUM, AttrDefaultOidIndexId, BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), elog, ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum, NoLock, ObjectIdGetDatum, relation_close(), relation_open(), RowExclusiveLock, ScanKeyInit(), SearchSysCacheCopy2, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

1776 {
1777  Relation attrdef_rel;
1778  Relation attr_rel;
1779  Relation myrel;
1780  ScanKeyData scankeys[1];
1781  SysScanDesc scan;
1782  HeapTuple tuple;
1783  Oid myrelid;
1784  AttrNumber myattnum;
1785 
1786  /* Grab an appropriate lock on the pg_attrdef relation */
1787  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1788 
1789  /* Find the pg_attrdef tuple */
1790  ScanKeyInit(&scankeys[0],
1791  Anum_pg_attrdef_oid,
1792  BTEqualStrategyNumber, F_OIDEQ,
1793  ObjectIdGetDatum(attrdefId));
1794 
1795  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1796  NULL, 1, scankeys);
1797 
1798  tuple = systable_getnext(scan);
1799  if (!HeapTupleIsValid(tuple))
1800  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1801 
1802  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1803  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1804 
1805  /* Get an exclusive lock on the relation owning the attribute */
1806  myrel = relation_open(myrelid, AccessExclusiveLock);
1807 
1808  /* Now we can delete the pg_attrdef row */
1809  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1810 
1811  systable_endscan(scan);
1812  table_close(attrdef_rel, RowExclusiveLock);
1813 
1814  /* Fix the pg_attribute row */
1815  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1816 
1817  tuple = SearchSysCacheCopy2(ATTNUM,
1818  ObjectIdGetDatum(myrelid),
1819  Int16GetDatum(myattnum));
1820  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1821  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1822  myattnum, myrelid);
1823 
1824  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1825 
1826  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1827 
1828  /*
1829  * Our update of the pg_attribute row will force a relcache rebuild, so
1830  * there's nothing else to do here.
1831  */
1832  table_close(attr_rel, RowExclusiveLock);
1833 
1834  /* Keep lock on attribute's rel until end of xact */
1835  relation_close(myrel, NoLock);
1836 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define Int16GetDatum(X)
Definition: postgres.h:451
#define AttrDefaultOidIndexId
Definition: indexing.h:91
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:176
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
int16 AttrNumber
Definition: attnum.h:21
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RemoveAttributeById()

void RemoveAttributeById ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 1607 of file heap.c.

References AccessExclusiveLock, 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().

1608 {
1609  Relation rel;
1610  Relation attr_rel;
1611  HeapTuple tuple;
1612  Form_pg_attribute attStruct;
1613  char newattname[NAMEDATALEN];
1614 
1615  /*
1616  * Grab an exclusive lock on the target table, which we will NOT release
1617  * until end of transaction. (In the simple case where we are directly
1618  * dropping this column, ATExecDropColumn already did this ... but when
1619  * cascading from a drop of some other object, we may not have any lock.)
1620  */
1621  rel = relation_open(relid, AccessExclusiveLock);
1622 
1623  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1624 
1625  tuple = SearchSysCacheCopy2(ATTNUM,
1626  ObjectIdGetDatum(relid),
1628  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1629  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1630  attnum, relid);
1631  attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
1632 
1633  if (attnum < 0)
1634  {
1635  /* System attribute (probably OID) ... just delete the row */
1636 
1637  CatalogTupleDelete(attr_rel, &tuple->t_self);
1638  }
1639  else
1640  {
1641  /* Dropping user attributes is lots harder */
1642 
1643  /* Mark the attribute as dropped */
1644  attStruct->attisdropped = true;
1645 
1646  /*
1647  * Set the type OID to invalid. A dropped attribute's type link
1648  * cannot be relied on (once the attribute is dropped, the type might
1649  * be too). Fortunately we do not need the type row --- the only
1650  * really essential information is the type's typlen and typalign,
1651  * which are preserved in the attribute's attlen and attalign. We set
1652  * atttypid to zero here as a means of catching code that incorrectly
1653  * expects it to be valid.
1654  */
1655  attStruct->atttypid = InvalidOid;
1656 
1657  /* Remove any NOT NULL constraint the column may have */
1658  attStruct->attnotnull = false;
1659 
1660  /* We don't want to keep stats for it anymore */
1661  attStruct->attstattarget = 0;
1662 
1663  /* Unset this so no one tries to look up the generation expression */
1664  attStruct->attgenerated = '\0';
1665 
1666  /*
1667  * Change the column name to something that isn't likely to conflict
1668  */
1669  snprintf(newattname, sizeof(newattname),
1670  "........pg.dropped.%d........", attnum);
1671  namestrcpy(&(attStruct->attname), newattname);
1672 
1673  /* clear the missing value if any */
1674  if (attStruct->atthasmissing)
1675  {
1676  Datum valuesAtt[Natts_pg_attribute];
1677  bool nullsAtt[Natts_pg_attribute];
1678  bool replacesAtt[Natts_pg_attribute];
1679 
1680  /* update the tuple - set atthasmissing and attmissingval */
1681  MemSet(valuesAtt, 0, sizeof(valuesAtt));
1682  MemSet(nullsAtt, false, sizeof(nullsAtt));
1683  MemSet(replacesAtt, false, sizeof(replacesAtt));
1684 
1685  valuesAtt[Anum_pg_attribute_atthasmissing - 1] =
1686  BoolGetDatum(false);
1687  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
1688  valuesAtt[Anum_pg_attribute_attmissingval - 1] = (Datum) 0;
1689  nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
1690  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
1691 
1692  tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
1693  valuesAtt, nullsAtt, replacesAtt);
1694  }
1695 
1696  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1697  }
1698 
1699  /*
1700  * Because updating the pg_attribute row will trigger a relcache flush for
1701  * the target relation, we need not do anything else to notify other
1702  * backends of the change.
1703  */
1704 
1705  table_close(attr_rel, RowExclusiveLock);
1706 
1707  if (attnum > 0)
1708  RemoveStatistics(relid, attnum);
1709 
1710  relation_close(rel, NoLock);
1711 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:482
#define Int16GetDatum(X)
Definition: postgres.h:451
#define MemSet(start, val, len)
Definition: c.h:971
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
int namestrcpy(Name name, const char *str)
Definition: name.c:250
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
uintptr_t Datum
Definition: postgres.h:367
#define BoolGetDatum(X)
Definition: postgres.h:402
#define InvalidOid
Definition: postgres_ext.h:36
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:3112
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define elog(elevel,...)
Definition: elog.h:214
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:176
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define snprintf
Definition: port.h:193

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

Definition at line 3647 of file heap.c.

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

Referenced by heap_drop_with_catalog().

3648 {
3649  Relation rel;
3650  HeapTuple tuple;
3651 
3652  rel = table_open(PartitionedRelationId, RowExclusiveLock);
3653 
3654  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3655  if (!HeapTupleIsValid(tuple))
3656  elog(ERROR, "cache lookup failed for partition key of relation %u",
3657  relid);
3658 
3659  CatalogTupleDelete(rel, &tuple->t_self);
3660 
3661  ReleaseSysCache(tuple);
3663 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 3112 of file heap.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), HeapTupleIsValid, Int16GetDatum, sort-test::key, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), StatisticRelidAttnumInhIndexId, 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().

3113 {
3114  Relation pgstatistic;
3115  SysScanDesc scan;
3116  ScanKeyData key[2];
3117  int nkeys;
3118  HeapTuple tuple;
3119 
3120  pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
3121 
3122  ScanKeyInit(&key[0],
3123  Anum_pg_statistic_starelid,
3124  BTEqualStrategyNumber, F_OIDEQ,
3125  ObjectIdGetDatum(relid));
3126 
3127  if (attnum == 0)
3128  nkeys = 1;
3129  else
3130  {
3131  ScanKeyInit(&key[1],
3132  Anum_pg_statistic_staattnum,
3133  BTEqualStrategyNumber, F_INT2EQ,
3135  nkeys = 2;
3136  }
3137 
3138  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
3139  NULL, nkeys, key);
3140 
3141  /* we must loop even when attnum != 0, in case of inherited stats */
3142  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3143  CatalogTupleDelete(pgstatistic, &tuple->t_self);
3144 
3145  systable_endscan(scan);
3146 
3147  table_close(pgstatistic, RowExclusiveLock);
3148 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define Int16GetDatum(X)
Definition: postgres.h:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define StatisticRelidAttnumInhIndexId
Definition: indexing.h:228
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ SetAttrMissing()

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

Definition at line 2088 of file heap.c.

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

Referenced by binary_upgrade_set_missing_value().

2089 {
2090  Datum valuesAtt[Natts_pg_attribute];
2091  bool nullsAtt[Natts_pg_attribute];
2092  bool replacesAtt[Natts_pg_attribute];
2093  Datum missingval;
2094  Form_pg_attribute attStruct;
2095  Relation attrrel,
2096  tablerel;
2097  HeapTuple atttup,
2098  newtup;
2099 
2100  /* lock the table the attribute belongs to */
2101  tablerel = table_open(relid, AccessExclusiveLock);
2102 
2103  /* Lock the attribute row and get the data */
2104  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2105  atttup = SearchSysCacheAttName(relid, attname);
2106  if (!HeapTupleIsValid(atttup))
2107  elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2108  attname, relid);
2109  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2110 
2111  /* get an array value from the value string */
2112  missingval = OidFunctionCall3(F_ARRAY_IN,
2114  ObjectIdGetDatum(attStruct->atttypid),
2115  Int32GetDatum(attStruct->atttypmod));
2116 
2117  /* update the tuple - set atthasmissing and attmissingval */
2118  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2119  MemSet(nullsAtt, false, sizeof(nullsAtt));
2120  MemSet(replacesAtt, false, sizeof(replacesAtt));
2121 
2122  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
2123  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2124  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2125  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2126 
2127  newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2128  valuesAtt, nullsAtt, replacesAtt);
2129  CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
2130 
2131  /* clean up */
2132  ReleaseSysCache(atttup);
2133  table_close(attrrel, RowExclusiveLock);
2134  table_close(tablerel, AccessExclusiveLock);
2135 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:482
#define MemSet(start, val, len)
Definition: c.h:971
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition: fmgr.h:666
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define BoolGetDatum(X)
Definition: postgres.h:402
static struct @143 value
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1257
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define Int32GetDatum(X)
Definition: postgres.h:479
#define elog(elevel,...)
Definition: elog.h:214
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113

◆ SetRelationNumChecks()

static void SetRelationNumChecks ( Relation  rel,
int  numchecks 
)
static

Definition at line 2912 of file heap.c.

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

2913 {
2914  Relation relrel;
2915  HeapTuple reltup;
2916  Form_pg_class relStruct;
2917 
2918  relrel = table_open(RelationRelationId, RowExclusiveLock);
2919  reltup = SearchSysCacheCopy1(RELOID,
2921  if (!HeapTupleIsValid(reltup))
2922  elog(ERROR, "cache lookup failed for relation %u",
2923  RelationGetRelid(rel));
2924  relStruct = (Form_pg_class) GETSTRUCT(reltup);
2925 
2926  if (relStruct->relchecks != numchecks)
2927  {
2928  relStruct->relchecks = numchecks;
2929 
2930  CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
2931  }
2932  else
2933  {
2934  /* Skip the disk update, but force relcache inval anyway */
2936  }
2937 
2938  heap_freetuple(reltup);
2939  table_close(relrel, RowExclusiveLock);
2940 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
#define elog(elevel,...)
Definition: elog.h:214
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ StoreAttrDefault()

Oid StoreAttrDefault ( Relation  rel,
AttrNumber  attnum,
Node expr,
bool  is_internal,
bool  add_column_mode 
)

Definition at line 2149 of file heap.c.

References ATTNUM, attnum, AttrDefaultOidIndexId, CatalogTupleInsert(), CatalogTupleUpdate(), ObjectAddress::classId, construct_array(), CreateExecutorState(), CStringGetTextDatum, DatumGetPointer, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, elog, ERROR, ExecEvalExpr(), ExecPrepareExpr(), expression_planner(), FreeExecutorState(), GetNewOidWithIndex(), GetPerTupleExprContext, GETSTRUCT, heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum, InvokeObjectPostCreateHookArg, MemSet, nodeToString(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, pfree(), PointerGetDatum, RelationData::rd_att, recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetDescr, RelationGetRelid, RowExclusiveLock, SearchSysCacheCopy2, HeapTupleData::t_self, table_close(), table_open(), TupleDescAttr, and values.

Referenced by AddRelationNewConstraints(), ATExecAlterColumnType(), and StoreConstraints().

2151 {
2152  char *adbin;
2153  Relation adrel;
2154  HeapTuple tuple;
2155  Datum values[4];
2156  static bool nulls[4] = {false, false, false, false};
2157  Relation attrrel;
2158  HeapTuple atttup;
2159  Form_pg_attribute attStruct;
2160  char attgenerated;
2161  Oid attrdefOid;
2162  ObjectAddress colobject,
2163  defobject;
2164 
2165  adrel = table_open(AttrDefaultRelationId, RowExclusiveLock);
2166 
2167  /*
2168  * Flatten expression to string form for storage.
2169  */
2170  adbin = nodeToString(expr);
2171 
2172  /*
2173  * Make the pg_attrdef entry.
2174  */
2175  attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId,
2176  Anum_pg_attrdef_oid);
2177  values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid);
2178  values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
2179  values[Anum_pg_attrdef_adnum - 1] = attnum;
2180  values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
2181 
2182  tuple = heap_form_tuple(adrel->rd_att, values, nulls);
2183  CatalogTupleInsert(adrel, tuple);
2184 
2185  defobject.classId = AttrDefaultRelationId;
2186  defobject.objectId = attrdefOid;
2187  defobject.objectSubId = 0;
2188 
2189  table_close(adrel, RowExclusiveLock);
2190 
2191  /* now can free some of the stuff allocated above */
2192  pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
2193  heap_freetuple(tuple);
2194  pfree(adbin);
2195 
2196  /*
2197  * Update the pg_attribute entry for the column to show that a default
2198  * exists.
2199  */
2200  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2201  atttup = SearchSysCacheCopy2(ATTNUM,
2204  if (!HeapTupleIsValid(atttup))
2205  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2206  attnum, RelationGetRelid(rel));
2207  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2208  attgenerated = attStruct->attgenerated;
2209  if (!attStruct->atthasdef)
2210  {
2211  Form_pg_attribute defAttStruct;
2212 
2213  ExprState *exprState;
2214  Expr *expr2 = (Expr *) expr;
2215  EState *estate = NULL;
2216  ExprContext *econtext;
2217  Datum valuesAtt[Natts_pg_attribute];
2218  bool nullsAtt[Natts_pg_attribute];
2219  bool replacesAtt[Natts_pg_attribute];
2220  Datum missingval = (Datum) 0;
2221  bool missingIsNull = true;
2222 
2223  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2224  MemSet(nullsAtt, false, sizeof(nullsAtt));
2225  MemSet(replacesAtt, false, sizeof(replacesAtt));
2226  valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2227  replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2228 
2229  if (add_column_mode && !attgenerated)
2230  {
2231  expr2 = expression_planner(expr2);
2232  estate = CreateExecutorState();
2233  exprState = ExecPrepareExpr(expr2, estate);
2234  econtext = GetPerTupleExprContext(estate);
2235 
2236  missingval = ExecEvalExpr(exprState, econtext,
2237  &missingIsNull);
2238 
2239  FreeExecutorState(estate);
2240 
2241  defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1);
2242 
2243  if (missingIsNull)
2244  {
2245  /* if the default evaluates to NULL, just store a NULL array */
2246  missingval = (Datum) 0;
2247  }
2248  else
2249  {
2250  /* otherwise make a one-element array of the value */
2251  missingval = PointerGetDatum(construct_array(&missingval,
2252  1,
2253  defAttStruct->atttypid,
2254  defAttStruct->attlen,
2255  defAttStruct->attbyval,
2256  defAttStruct->attalign));
2257  }
2258 
2259  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
2260  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2261  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2262  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2263  nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull;
2264  }
2265  atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2266  valuesAtt, nullsAtt, replacesAtt);
2267 
2268  CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
2269 
2270  if (!missingIsNull)
2271  pfree(DatumGetPointer(missingval));
2272 
2273  }
2274  table_close(attrrel, RowExclusiveLock);
2275  heap_freetuple(atttup);
2276 
2277  /*
2278  * Make a dependency so that the pg_attrdef entry goes away if the column
2279  * (or whole table) is deleted.
2280  */
2281  colobject.classId = RelationRelationId;
2282  colobject.objectId = RelationGetRelid(rel);
2283  colobject.objectSubId = attnum;
2284 
2285  recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
2286 
2287  /*
2288  * Record dependencies on objects used in the expression, too.
2289  */
2290  if (attgenerated)
2291  {
2292  /*
2293  * Generated column: Dropping anything that the generation expression
2294  * refers to automatically drops the generated column.
2295  */
2296  recordDependencyOnSingleRelExpr(&colobject, expr, RelationGetRelid(rel),
2298  DEPENDENCY_AUTO, false);
2299  }
2300  else
2301  {
2302  /*
2303  * Normal default: Dropping anything that the default refers to
2304  * requires CASCADE and drops the default only.
2305  */
2306  recordDependencyOnSingleRelExpr(&defobject, expr, RelationGetRelid(rel),
2308  DEPENDENCY_NORMAL, false);
2309  }
2310 
2311  /*
2312  * Post creation hook for attribute defaults.
2313  *
2314  * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
2315  * couple of deletion/creation of the attribute's default entry, so the
2316  * callee should check existence of an older version of this entry if it
2317  * needs to distinguish.
2318  */
2319  InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
2320  RelationGetRelid(rel), attnum, is_internal);
2321 
2322  return attrdefOid;
2323 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:317
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:482
#define PointerGetDatum(X)
Definition: postgres.h:556
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Expr * expression_planner(Expr *expr)
Definition: planner.c:6156
#define Int16GetDatum(X)
Definition: postgres.h:451
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3292
#define AttrDefaultOidIndexId
Definition: indexing.h:91
#define MemSet(start, val, len)
Definition: c.h:971
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:492
void FreeExecutorState(EState *estate)
Definition: execUtils.c:191
#define GetPerTupleExprContext(estate)
Definition: executor.h:507
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:290
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
EState * CreateExecutorState(void)
Definition: execUtils.c:89
uintptr_t Datum
Definition: postgres.h:367
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:153
TupleDesc rd_att
Definition: rel.h:110
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
Definition: dependency.c:1625
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define DatumGetPointer(X)
Definition: postgres.h:549
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define elog(elevel,...)
Definition: elog.h:214
#define CStringGetTextDatum(s)
Definition: builtins.h:87
char * nodeToString(const void *obj)
Definition: outfuncs.c:4360
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:176
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define RelationGetRelid(relation)
Definition: rel.h:456
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ StoreConstraints()

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

Definition at line 2442 of file heap.c.

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

2443 {
2444  int numchecks = 0;
2445  ListCell *lc;
2446 
2447  if (cooked_constraints == NIL)
2448  return; /* nothing to do */
2449 
2450  /*
2451  * Deparsing of constraint expressions will fail unless the just-created
2452  * pg_attribute tuples for this relation are made visible. So, bump the
2453  * command counter. CAUTION: this will cause a relcache entry rebuild.
2454  */
2456 
2457  foreach(lc, cooked_constraints)
2458  {
2459  CookedConstraint *con = (CookedConstraint *) lfirst(lc);
2460 
2461  switch (con->contype)
2462  {
2463  case CONSTR_DEFAULT:
2464  con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
2465  is_internal, false);
2466  break;
2467  case CONSTR_CHECK:
2468  con->conoid =
2469  StoreRelCheck(rel, con->name, con->expr,
2470  !con->skip_validation, con->is_local,
2471  con->inhcount, con->is_no_inherit,
2472  is_internal);
2473  numchecks++;
2474  break;
2475  default:
2476  elog(ERROR, "unrecognized constraint type: %d",
2477  (int) con->contype);
2478  }
2479  }
2480 
2481  if (numchecks > 0)
2482  SetRelationNumChecks(rel, numchecks);
2483 }
#define NIL
Definition: pg_list.h:65
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2912
bool is_no_inherit
Definition: heap.h:45
AttrNumber attnum
Definition: heap.h:40
#define ERROR
Definition: elog.h:43
int inhcount
Definition: heap.h:44
bool skip_validation
Definition: heap.h:42
ConstrType contype
Definition: heap.h:37
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal, bool add_column_mode)
Definition: heap.c:2149
void CommandCounterIncrement(void)
Definition: xact.c:1006
#define lfirst(lc)
Definition: pg_list.h:190
#define elog(elevel,...)
Definition: elog.h:214
Oid conoid
Definition: heap.h:38
Node * expr
Definition: heap.h:41
char * name
Definition: heap.h:39
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:2334
bool is_local
Definition: heap.h:43

◆ StorePartitionBound()

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

Definition at line 3678 of file heap.c.

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

3679 {
3680  Relation classRel;
3681  HeapTuple tuple,
3682  newtuple;
3683  Datum new_val[Natts_pg_class];
3684  bool new_null[Natts_pg_class],
3685  new_repl[Natts_pg_class];
3686  Oid defaultPartOid;
3687 
3688  /* Update pg_class tuple */
3689  classRel = table_open(RelationRelationId, RowExclusiveLock);
3690  tuple = SearchSysCacheCopy1(RELOID,
3692  if (!HeapTupleIsValid(tuple))
3693  elog(ERROR, "cache lookup failed for relation %u",
3694  RelationGetRelid(rel));
3695 
3696 #ifdef USE_ASSERT_CHECKING
3697  {
3698  Form_pg_class classForm;
3699  bool isnull;
3700 
3701  classForm = (Form_pg_class) GETSTRUCT(tuple);
3702  Assert(!classForm->relispartition);
3703  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3704  &isnull);
3705  Assert(isnull);
3706  }
3707 #endif
3708 
3709  /* Fill in relpartbound value */
3710  memset(new_val, 0, sizeof(new_val));
3711  memset(new_null, false, sizeof(new_null));
3712  memset(new_repl, false, sizeof(new_repl));
3713  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3714  new_null[Anum_pg_class_relpartbound - 1] = false;
3715  new_repl[Anum_pg_class_relpartbound - 1] = true;
3716  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3717  new_val, new_null, new_repl);
3718  /* Also set the flag */
3719  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3720  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3721  heap_freetuple(newtuple);
3722  table_close(classRel, RowExclusiveLock);
3723 
3724  /*
3725  * If we're storing bounds for the default partition, update
3726  * pg_partitioned_table too.
3727  */
3728  if (bound->is_default)
3730  RelationGetRelid(rel));
3731 
3732  /* Make these updates visible */
3734 
3735  /*
3736  * The partition constraint for the default partition depends on the
3737  * partition bounds of every other partition, so we must invalidate the
3738  * relcache entry for that partition every time a partition is added or
3739  * removed.
3740  */
3741  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3742  if (OidIsValid(defaultPartOid))
3743  CacheInvalidateRelcacheByRelid(defaultPartOid);
3744 
3745  CacheInvalidateRelcache(parent);
3746 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:482
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:315
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
PartitionDesc RelationGetPartitionDesc(Relation rel)
Definition: partdesc.c:65
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1329
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1006
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
#define elog(elevel,...)
Definition: elog.h:214
#define CStringGetTextDatum(s)
Definition: builtins.h:87
char * nodeToString(const void *obj)
Definition: outfuncs.c:4360
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define RelationGetRelid(relation)
Definition: rel.h:456
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
Definition: partdesc.c:361

◆ StorePartitionKey()

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

Definition at line 3515 of file heap.c.

References Assert, buildint2vector(), buildoidvector(), CacheInvalidateRelcache(), CatalogTupleInsert(), CharGetDatum, ObjectAddress::classId, CStringGetTextDatum, DEPENDENCY_INTERNAL, DEPENDENCY_NORMAL, heap_form_tuple(), i, Int16GetDatum, InvalidOid, MemSet, nodeToString(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, pfree(), PointerGetDatum, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetDescr, RelationGetRelid, RowExclusiveLock, table_close(), table_open(), and values.

Referenced by DefineRelation().

3522 {
3523  int i;
3524  int2vector *partattrs_vec;
3525  oidvector *partopclass_vec;
3526  oidvector *partcollation_vec;
3527  Datum partexprDatum;
3528  Relation pg_partitioned_table;
3529  HeapTuple tuple;
3530  Datum values[Natts_pg_partitioned_table];
3531  bool nulls[Natts_pg_partitioned_table];
3532  ObjectAddress myself;
3533  ObjectAddress referenced;
3534 
3535  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3536 
3537  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3538  partattrs_vec = buildint2vector(partattrs, partnatts);
3539  partopclass_vec = buildoidvector(partopclass, partnatts);
3540  partcollation_vec = buildoidvector(partcollation, partnatts);
3541 
3542  /* Convert the expressions (if any) to a text datum */
3543  if (partexprs)
3544  {
3545  char *exprString;
3546 
3547  exprString = nodeToString(partexprs);
3548  partexprDatum = CStringGetTextDatum(exprString);
3549  pfree(exprString);
3550  }
3551  else
3552  partexprDatum = (Datum) 0;
3553 
3554  pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
3555 
3556  MemSet(nulls, false, sizeof(nulls));
3557 
3558  /* Only this can ever be NULL */
3559  if (!partexprDatum)
3560  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3561 
3562  values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
3563  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3564  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3565  values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
3566  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3567  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3568  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3569  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3570 
3571  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3572 
3573  CatalogTupleInsert(pg_partitioned_table, tuple);
3574  table_close(pg_partitioned_table, RowExclusiveLock);
3575 
3576  /* Mark this relation as dependent on a few things as follows */
3577  myself.classId = RelationRelationId;
3578  myself.objectId = RelationGetRelid(rel);
3579  myself.objectSubId = 0;
3580 
3581  /* Operator class and collation per key column */
3582  for (i = 0; i < partnatts; i++)
3583  {
3584  referenced.classId = OperatorClassRelationId;
3585  referenced.objectId = partopclass[i];
3586  referenced.objectSubId = 0;
3587 
3588  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3589 
3590  /* The default collation is pinned, so don't bother recording it */
3591  if (OidIsValid(partcollation[i]) &&
3592  partcollation[i] != DEFAULT_COLLATION_OID)
3593  {
3594  referenced.classId = CollationRelationId;
3595  referenced.objectId = partcollation[i];
3596  referenced.objectSubId = 0;
3597 
3598  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3599  }
3600  }
3601 
3602  /*
3603  * The partitioning columns are made internally dependent on the table,
3604  * because we cannot drop any of them without dropping the whole table.
3605  * (ATExecDropColumn independently enforces that, but it's not bulletproof
3606  * so we need the dependencies too.)
3607  */
3608  for (i = 0; i < partnatts; i++)
3609  {
3610  if (partattrs[i] == 0)
3611  continue; /* ignore expressions here */
3612 
3613  referenced.classId = RelationRelationId;
3614  referenced.objectId = RelationGetRelid(rel);
3615  referenced.objectSubId = partattrs[i];
3616 
3617  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
3618  }
3619 
3620  /*
3621  * Also consider anything mentioned in partition expressions. External
3622  * references (e.g. functions) get NORMAL dependencies. Table columns
3623  * mentioned in the expressions are handled the same as plain partitioning
3624  * columns, i.e. they become internally dependent on the whole table.
3625  */
3626  if (partexprs)
3628  (Node *) partexprs,
3629  RelationGetRelid(rel),
3632  true /* reverse the self-deps */ );
3633 
3634  /*
3635  * We must invalidate the relcache so that the next
3636  * CommandCounterIncrement() will cause the same to be rebuilt using the
3637  * information in just created catalog entry.
3638  */
3640 }
Definition: c.h:594
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define RelationGetDescr(relation)
Definition: rel.h:482
#define PointerGetDatum(X)
Definition: postgres.h:556
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:114
#define Int16GetDatum(X)
Definition: postgres.h:451
Definition: nodes.h:529
#define MemSet(start, val, len)
Definition: c.h:971
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
Form_pg_class rd_rel
Definition: rel.h:109
#define OidIsValid(objectId)
Definition: c.h:644
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define RowExclusiveLock
Definition: lockdefs.h:38
Definition: c.h:583
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:738
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:167
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
Definition: dependency.c:1625
#define CharGetDatum(X)
Definition: postgres.h:416
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:87
char * nodeToString(const void *obj)
Definition: outfuncs.c:4360
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:456
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

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

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

Referenced by AddRelationNewConstraints(), and StoreConstraints().

2337 {
2338  char *ccbin;
2339  List *varList;
2340  int keycount;
2341  int16 *attNos;
2342  Oid constrOid;
2343 
2344  /*
2345  * Flatten expression to string form for storage.
2346  */
2347  ccbin = nodeToString(expr);
2348 
2349  /*
2350  * Find columns of rel that are used in expr
2351  *
2352  * NB: pull_var_clause is okay here only because we don't allow subselects
2353  * in check constraints; it would fail to examine the contents of
2354  * subselects.
2355  */
2356  varList = pull_var_clause(expr, 0);
2357  keycount = list_length(varList);
2358 
2359  if (keycount > 0)
2360  {
2361  ListCell *vl;
2362  int i = 0;
2363 
2364  attNos = (int16 *) palloc(keycount * sizeof(int16));
2365  foreach(vl, varList)
2366  {
2367  Var *var = (Var *) lfirst(vl);
2368  int j;
2369 
2370  for (j = 0; j < i; j++)
2371  if (attNos[j] == var->varattno)
2372  break;
2373  if (j == i)
2374  attNos[i++] = var->varattno;
2375  }
2376  keycount = i;
2377  }
2378  else
2379  attNos = NULL;
2380 
2381  /*
2382  * Partitioned tables do not contain any rows themselves, so a NO INHERIT
2383  * constraint makes no sense.
2384  */
2385  if (is_no_inherit &&
2386  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2387  ereport(ERROR,
2388  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2389  errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
2390  RelationGetRelationName(rel))));
2391 
2392  /*
2393  * Create the Check Constraint
2394  */
2395  constrOid =
2396  CreateConstraintEntry(ccname, /* Constraint Name */
2397  RelationGetNamespace(rel), /* namespace */
2398  CONSTRAINT_CHECK, /* Constraint Type */
2399  false, /* Is Deferrable */
2400  false, /* Is Deferred */
2401  is_validated,
2402  InvalidOid, /* no parent constraint */
2403  RelationGetRelid(rel), /* relation */
2404  attNos, /* attrs in the constraint */
2405  keycount, /* # key attrs in the constraint */
2406  keycount, /* # total attrs in the constraint */
2407  InvalidOid, /* not a domain constraint */
2408  InvalidOid, /* no associated index */
2409  InvalidOid, /* Foreign key fields */
2410  NULL,
2411  NULL,
2412  NULL,
2413  NULL,
2414  0,
2415  ' ',
2416  ' ',
2417  ' ',
2418  NULL, /* not an exclusion constraint */
2419  expr, /* Tree form of check constraint */
2420  ccbin, /* Binary form of check constraint */
2421  is_local, /* conislocal */
2422  inhcount, /* coninhcount */
2423  is_no_inherit, /* connoinherit */
2424  is_internal); /* internally constructed? */
2425 
2426  pfree(ccbin);
2427 
2428  return constrOid;
2429 }
signed short int16
Definition: c.h:354
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, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
Definition: pg_constraint.c:50
int errcode(int sqlerrcode)
Definition: elog.c:610
AttrNumber varattno
Definition: primnodes.h:186
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:181
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
char * nodeToString(const void *obj)
Definition: outfuncs.c:4360
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:456
#define RelationGetNamespace(relation)
Definition: rel.h:497

◆ SystemAttributeByName()

const FormData_pg_attribute* SystemAttributeByName ( const char *  attname)

Definition at line 261 of file heap.c.

References FormData_pg_attribute, lengthof, NameStr, and SysAtt.

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

262 {
263  int j;
264 
265  for (j = 0; j < (int) lengthof(SysAtt); j++)
266  {
267  const FormData_pg_attribute *att = SysAtt[j];
268 
269  if (strcmp(NameStr(att->attname), attname) == 0)
270  return att;
271  }
272 
273  return NULL;
274 }
#define lengthof(array)
Definition: c.h:668
NameData attname
Definition: pg_attribute.h:40
FormData_pg_attribute
Definition: pg_attribute.h:177
static const FormData_pg_attribute * SysAtt[]
Definition: heap.c:241
#define NameStr(name)
Definition: c.h:615

◆ SystemAttributeDefinition()

const FormData_pg_attribute* SystemAttributeDefinition ( AttrNumber  attno)

Definition at line 249 of file heap.c.

References elog, ERROR, FormData_pg_attribute, lengthof, and SysAtt.

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

250 {
251  if (attno >= 0 || attno < -(int) lengthof(SysAtt))
252  elog(ERROR, "invalid system attribute number %d", attno);
253  return SysAtt[-attno - 1];
254 }
#define lengthof(array)
Definition: c.h:668
#define ERROR
Definition: elog.h:43
static const FormData_pg_attribute * SysAtt[]
Definition: heap.c:241
#define elog(elevel,...)
Definition: elog.h:214

Variable Documentation

◆ a1

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

Definition at line 151 of file heap.c.

Referenced by aclitem_eq(), aclitemComparator(), cmpaffix(), deccall2(), deccall3(), evalLazyFunc(), inet_merge(), inet_same_family(), int4gcd_internal(), int8gcd_internal(), macaddr8_cmp(), macaddr8_eq(), macaddr8_ge(), macaddr8_gt(), macaddr8_le(), macaddr8_lt(), macaddr8_ne(), macaddr_cmp(), macaddr_eq(), macaddr_ge(), macaddr_gt(), macaddr_le(), macaddr_lt(), macaddr_ne(), MergeAffix(), network_cmp(), 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(), and sqrt_var().

◆ a2

◆ a3

const FormData_pg_attribute a3
static
Initial value:
= {
.attname = {"cmin"},
.atttypid = CIDOID,
.attlen = sizeof(CommandId),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = true,
.attstorage = TYPSTORAGE_PLAIN,
.attalign = TYPALIGN_INT,
.attnotnull = true,
.attislocal = true,
}
uint32 CommandId
Definition: c.h:527
char attstorage
Definition: pg_attribute.h:116
bool attnotnull
Definition: pg_attribute.h:125
#define MinCommandIdAttributeNumber
Definition: sysattr.h:23
bool attbyval
Definition: pg_attribute.h:108
char attalign
Definition: pg_attribute.h:122
int16 attnum
Definition: pg_attribute.h:79

Definition at line 179 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,
.attstorage = TYPSTORAGE_PLAIN,
.attalign = TYPALIGN_INT,
.attnotnull = true,
.attislocal = true,
}
char attstorage
Definition: pg_attribute.h:116
bool attnotnull
Definition: pg_attribute.h:125
uint32 TransactionId
Definition: c.h:513
bool attbyval
Definition: pg_attribute.h:108
char attalign
Definition: pg_attribute.h:122
#define MaxTransactionIdAttributeNumber
Definition: sysattr.h:24
int16 attnum
Definition: pg_attribute.h:79

Definition at line 193 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,
.attstorage = TYPSTORAGE_PLAIN,
.attalign = TYPALIGN_INT,
.attnotnull = true,
.attislocal = true,
}
uint32 CommandId
Definition: c.h:527
char attstorage
Definition: pg_attribute.h:116
bool attnotnull
Definition: pg_attribute.h:125
bool attbyval
Definition: pg_attribute.h:108
char attalign
Definition: pg_attribute.h:122
#define MaxCommandIdAttributeNumber
Definition: sysattr.h:25
int16 attnum
Definition: pg_attribute.h:79

Definition at line 207 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,
.attstorage = TYPSTORAGE_PLAIN,
.attalign = TYPALIGN_INT,
.attnotnull = true,
.attislocal = true,
}
char attstorage
Definition: pg_attribute.h:116
bool attnotnull
Definition: pg_attribute.h:125
unsigned int Oid
Definition: postgres_ext.h:31
bool attbyval
Definition: pg_attribute.h:108
char attalign
Definition: pg_attribute.h:122
#define TableOidAttributeNumber
Definition: sysattr.h:26
int16 attnum
Definition: pg_attribute.h:79

Definition at line 227 of file heap.c.

◆ binary_upgrade_next_heap_pg_class_oid

Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid

Definition at line 92 of file heap.c.

Referenced by binary_upgrade_set_next_heap_pg_class_oid(), and heap_create_with_catalog().

◆ binary_upgrade_next_toast_pg_class_oid

Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid

◆ SysAtt

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

Definition at line 241 of file heap.c.

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