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/toast_compression.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 InsertPgAttributeTuples (Relation pg_attribute_rel, TupleDesc tupdesc, Oid new_rel_oid, Datum *attoptions, CatalogIndexState indstate)
 
static void AddNewAttributeTuples (Oid new_rel_oid, TupleDesc tupdesc, char relkind)
 
void InsertPgClassTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
 
Oid heap_create_with_catalog (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid reltypeid, Oid reloftypeid, Oid ownerid, Oid accessmtd, TupleDesc tupdesc, List *cooked_constraints, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, OnCommitAction oncommit, Datum reloptions, bool use_user_acl, bool allow_system_table_mods, bool is_internal, Oid relrewrite, ObjectAddress *typaddress)
 
void DeleteRelationTuple (Oid relid)
 
void DeleteAttributeTuples (Oid relid)
 
void DeleteSystemAttributeTuples (Oid relid)
 
void RemoveAttributeById (Oid relid, AttrNumber attnum)
 
void 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 CopyStatistics (Oid fromrelid, Oid torelid)
 
void RemoveStatistics (Oid relid, AttrNumber attnum)
 
static void RelationTruncateIndexes (Relation heapRelation)
 
void heap_truncate (List *relids)
 
void heap_truncate_one_rel (Relation rel)
 
void heap_truncate_check_FKs (List *relations, bool tempTables)
 
Listheap_truncate_find_FKs (List *relationIds)
 
void StorePartitionKey (Relation rel, char strategy, int16 partnatts, AttrNumber *partattrs, List *partexprs, Oid *partopclass, Oid *partcollation)
 
void RemovePartitionKeyByRelId (Oid relid)
 
void StorePartitionBound (Relation rel, Relation parent, PartitionBoundSpec *bound)
 

Variables

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

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

Referenced by heap_create_with_catalog().

847 {
848  Relation rel;
849  CatalogIndexState indstate;
850  int natts = tupdesc->natts;
851  ObjectAddress myself,
852  referenced;
853 
854  /*
855  * open pg_attribute and its indexes.
856  */
857  rel = table_open(AttributeRelationId, RowExclusiveLock);
858 
859  indstate = CatalogOpenIndexes(rel);
860 
861  /* set stats detail level to a sane default */
862  for (int i = 0; i < natts; i++)
863  tupdesc->attrs[i].attstattarget = -1;
864  InsertPgAttributeTuples(rel, tupdesc, new_rel_oid, NULL, indstate);
865 
866  /* add dependencies on their datatypes and collations */
867  for (int i = 0; i < natts; i++)
868  {
869  /* Add dependency info */
870  ObjectAddressSubSet(myself, RelationRelationId, new_rel_oid, i + 1);
871  ObjectAddressSet(referenced, TypeRelationId,
872  tupdesc->attrs[i].atttypid);
873  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
874 
875  /* The default collation is pinned, so don't bother recording it */
876  if (OidIsValid(tupdesc->attrs[i].attcollation) &&
877  tupdesc->attrs[i].attcollation != DEFAULT_COLLATION_OID)
878  {
879  ObjectAddressSet(referenced, CollationRelationId,
880  tupdesc->attrs[i].attcollation);
881  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
882  }
883  }
884 
885  /*
886  * Next we add the system attributes. Skip OID if rel has no OIDs. Skip
887  * all for a view or type relation. We don't bother with making datatype
888  * dependencies here, since presumably all these types are pinned.
889  */
890  if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
891  {
892  TupleDesc td;
893 
895 
896  InsertPgAttributeTuples(rel, td, new_rel_oid, NULL, indstate);
897  FreeTupleDesc(td);
898  }
899 
900  /*
901  * clean up
902  */
903  CatalogCloseIndexes(indstate);
904 
906 }
FormData_pg_attribute attrs[FLEXIBLE_ARRAY_MEMBER]
Definition: tupdesc.h:87
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
#define lengthof(array)
Definition: c.h:734
#define OidIsValid(objectId)
Definition: c.h:710
#define RowExclusiveLock
Definition: lockdefs.h:38
void InsertPgAttributeTuples(Relation pg_attribute_rel, TupleDesc tupdesc, Oid new_rel_oid, Datum *attoptions, CatalogIndexState indstate)
Definition: heap.c:740
FormData_pg_attribute
Definition: pg_attribute.h:187
static const FormData_pg_attribute * SysAtt[]
Definition: heap.c:242
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:43
#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
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:309
int i
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:61
TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs)
Definition: tupdesc.c:90
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 995 of file heap.c.

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

Referenced by heap_create_with_catalog().

1006 {
1007  Form_pg_class new_rel_reltup;
1008 
1009  /*
1010  * first we update some of the information in our uncataloged relation's
1011  * relation descriptor.
1012  */
1013  new_rel_reltup = new_rel_desc->rd_rel;
1014 
1015  switch (relkind)
1016  {
1017  case RELKIND_RELATION:
1018  case RELKIND_MATVIEW:
1019  case RELKIND_INDEX:
1020  case RELKIND_TOASTVALUE:
1021  /* The relation is real, but as yet empty */
1022  new_rel_reltup->relpages = 0;
1023  new_rel_reltup->reltuples = -1;
1024  new_rel_reltup->relallvisible = 0;
1025  break;
1026  case RELKIND_SEQUENCE:
1027  /* Sequences always have a known size */
1028  new_rel_reltup->relpages = 1;
1029  new_rel_reltup->reltuples = 1;
1030  new_rel_reltup->relallvisible = 0;
1031  break;
1032  default:
1033  /* Views, etc, have no disk storage */
1034  new_rel_reltup->relpages = 0;
1035  new_rel_reltup->reltuples = -1;
1036  new_rel_reltup->relallvisible = 0;
1037  break;
1038  }
1039 
1040  new_rel_reltup->relfrozenxid = relfrozenxid;
1041  new_rel_reltup->relminmxid = relminmxid;
1042  new_rel_reltup->relowner = relowner;
1043  new_rel_reltup->reltype = new_type_oid;
1044  new_rel_reltup->reloftype = reloftype;
1045 
1046  /* relispartition is always set by updating this tuple later */
1047  new_rel_reltup->relispartition = false;
1048 
1049  /* fill rd_att's type ID with something sane even if reltype is zero */
1050  new_rel_desc->rd_att->tdtypeid = new_type_oid ? new_type_oid : RECORDOID;
1051  new_rel_desc->rd_att->tdtypmod = -1;
1052 
1053  /* Now build and insert the tuple */
1054  InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid,
1055  relacl, reloptions);
1056 }
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:922
int32 tdtypmod
Definition: tupdesc.h:83
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 1066 of file heap.c.

References DEFAULT_TYPDELIM, InvalidOid, and TypeCreate().

Referenced by heap_create_with_catalog().

1073 {
1074  return
1075  TypeCreate(new_row_type, /* optional predetermined OID */
1076  typeName, /* type name */
1077  typeNamespace, /* type namespace */
1078  new_rel_oid, /* relation oid */
1079  new_rel_kind, /* relation kind */
1080  ownerid, /* owner's ID */
1081  -1, /* internal size (varlena) */
1082  TYPTYPE_COMPOSITE, /* type-type (composite) */
1083  TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
1084  false, /* composite types are never preferred */
1085  DEFAULT_TYPDELIM, /* default array delimiter */
1086  F_RECORD_IN, /* input procedure */
1087  F_RECORD_OUT, /* output procedure */
1088  F_RECORD_RECV, /* receive procedure */
1089  F_RECORD_SEND, /* send procedure */
1090  InvalidOid, /* typmodin procedure - none */
1091  InvalidOid, /* typmodout procedure - none */
1092  InvalidOid, /* analyze procedure - default */
1093  InvalidOid, /* subscript procedure - none */
1094  InvalidOid, /* array element type - irrelevant */
1095  false, /* this is not an array type */
1096  new_array_type, /* array type if any */
1097  InvalidOid, /* domain base type - irrelevant */
1098  NULL, /* default value - none */
1099  NULL, /* default binary representation */
1100  false, /* passed by reference */
1101  TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1102  TYPSTORAGE_EXTENDED, /* fully TOASTable */
1103  -1, /* typmod */
1104  0, /* array dimensions for typBaseType */
1105  false, /* Type NOT NULL */
1106  InvalidOid); /* rowtypes never have a collation */
1107 }
#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 subscriptProcedure, Oid elementType, bool isImplicitArray, Oid arrayType, Oid baseType, const char *defaultTypeValue, char *defaultTypeBin, bool passedByValue, char alignment, char storage, int32 typeMod, int32 typNDims, bool typeNotNull, Oid typeCollation)
Definition: pg_type.c:197

◆ AddRelationNewConstraints()

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

Definition at line 2576 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().

2583 {
2584  List *cookedConstraints = NIL;
2585  TupleDesc tupleDesc;
2586  TupleConstr *oldconstr;
2587  int numoldchecks;
2588  ParseState *pstate;
2589  ParseNamespaceItem *nsitem;
2590  int numchecks;
2591  List *checknames;
2592  ListCell *cell;
2593  Node *expr;
2594  CookedConstraint *cooked;
2595 
2596  /*
2597  * Get info about existing constraints.
2598  */
2599  tupleDesc = RelationGetDescr(rel);
2600  oldconstr = tupleDesc->constr;
2601  if (oldconstr)
2602  numoldchecks = oldconstr->num_check;
2603  else
2604  numoldchecks = 0;
2605 
2606  /*
2607  * Create a dummy ParseState and insert the target relation as its sole
2608  * rangetable entry. We need a ParseState for transformExpr.
2609  */
2610  pstate = make_parsestate(NULL);
2611  pstate->p_sourcetext = queryString;
2612  nsitem = addRangeTableEntryForRelation(pstate,
2613  rel,
2615  NULL,
2616  false,
2617  true);
2618  addNSItemToQuery(pstate, nsitem, true, true, true);
2619 
2620  /*
2621  * Process column default expressions.
2622  */
2623  foreach(cell, newColDefaults)
2624  {
2625  RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
2626  Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
2627  Oid defOid;
2628 
2629  expr = cookDefault(pstate, colDef->raw_default,
2630  atp->atttypid, atp->atttypmod,
2631  NameStr(atp->attname),
2632  atp->attgenerated);
2633 
2634  /*
2635  * If the expression is just a NULL constant, we do not bother to make
2636  * an explicit pg_attrdef entry, since the default behavior is
2637  * equivalent. This applies to column defaults, but not for
2638  * generation expressions.
2639  *
2640  * Note a nonobvious property of this test: if the column is of a
2641  * domain type, what we'll get is not a bare null Const but a
2642  * CoerceToDomain expr, so we will not discard the default. This is
2643  * critical because the column default needs to be retained to
2644  * override any default that the domain might have.
2645  */
2646  if (expr == NULL ||
2647  (!colDef->generated &&
2648  IsA(expr, Const) &&
2649  castNode(Const, expr)->constisnull))
2650  continue;
2651 
2652  /* If the DEFAULT is volatile we cannot use a missing value */
2653  if (colDef->missingMode && contain_volatile_functions((Node *) expr))
2654  colDef->missingMode = false;
2655 
2656  defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal,
2657  colDef->missingMode);
2658 
2659  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2660  cooked->contype = CONSTR_DEFAULT;
2661  cooked->conoid = defOid;
2662  cooked->name = NULL;
2663  cooked->attnum = colDef->attnum;
2664  cooked->expr = expr;
2665  cooked->skip_validation = false;
2666  cooked->is_local = is_local;
2667  cooked->inhcount = is_local ? 0 : 1;
2668  cooked->is_no_inherit = false;
2669  cookedConstraints = lappend(cookedConstraints, cooked);
2670  }
2671 
2672  /*
2673  * Process constraint expressions.
2674  */
2675  numchecks = numoldchecks;
2676  checknames = NIL;
2677  foreach(cell, newConstraints)
2678  {
2679  Constraint *cdef = (Constraint *) lfirst(cell);
2680  char *ccname;
2681  Oid constrOid;
2682 
2683  if (cdef->contype != CONSTR_CHECK)
2684  continue;
2685 
2686  if (cdef->raw_expr != NULL)
2687  {
2688  Assert(cdef->cooked_expr == NULL);
2689 
2690  /*
2691  * Transform raw parsetree to executable expression, and verify
2692  * it's valid as a CHECK constraint.
2693  */
2694  expr = cookConstraint(pstate, cdef->raw_expr,
2696  }
2697  else
2698  {
2699  Assert(cdef->cooked_expr != NULL);
2700 
2701  /*
2702  * Here, we assume the parser will only pass us valid CHECK
2703  * expressions, so we do no particular checking.
2704  */
2705  expr = stringToNode(cdef->cooked_expr);
2706  }
2707 
2708  /*
2709  * Check name uniqueness, or generate a name if none was given.
2710  */
2711  if (cdef->conname != NULL)
2712  {
2713  ListCell *cell2;
2714 
2715  ccname = cdef->conname;
2716  /* Check against other new constraints */
2717  /* Needed because we don't do CommandCounterIncrement in loop */
2718  foreach(cell2, checknames)
2719  {
2720  if (strcmp((char *) lfirst(cell2), ccname) == 0)
2721  ereport(ERROR,
2723  errmsg("check constraint \"%s\" already exists",
2724  ccname)));
2725  }
2726 
2727  /* save name for future checks */
2728  checknames = lappend(checknames, ccname);
2729 
2730  /*
2731  * Check against pre-existing constraints. If we are allowed to
2732  * merge with an existing constraint, there's no more to do here.
2733  * (We omit the duplicate constraint from the result, which is
2734  * what ATAddCheckConstraint wants.)
2735  */
2736  if (MergeWithExistingConstraint(rel, ccname, expr,
2737  allow_merge, is_local,
2738  cdef->initially_valid,
2739  cdef->is_no_inherit))
2740  continue;
2741  }
2742  else
2743  {
2744  /*
2745  * When generating a name, we want to create "tab_col_check" for a
2746  * column constraint and "tab_check" for a table constraint. We
2747  * no longer have any info about the syntactic positioning of the
2748  * constraint phrase, so we approximate this by seeing whether the
2749  * expression references more than one column. (If the user
2750  * played by the rules, the result is the same...)
2751  *
2752  * Note: pull_var_clause() doesn't descend into sublinks, but we
2753  * eliminated those above; and anyway this only needs to be an
2754  * approximate answer.
2755  */
2756  List *vars;
2757  char *colname;
2758 
2759  vars = pull_var_clause(expr, 0);
2760 
2761  /* eliminate duplicates */
2762  vars = list_union(NIL, vars);
2763 
2764  if (list_length(vars) == 1)
2765  colname = get_attname(RelationGetRelid(rel),
2766  ((Var *) linitial(vars))->varattno,
2767  true);
2768  else
2769  colname = NULL;
2770 
2772  colname,
2773  "check",
2774  RelationGetNamespace(rel),
2775  checknames);
2776 
2777  /* save name for future checks */
2778  checknames = lappend(checknames, ccname);
2779  }
2780 
2781  /*
2782  * OK, store it.
2783  */
2784  constrOid =
2785  StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
2786  is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
2787 
2788  numchecks++;
2789 
2790  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2791  cooked->contype = CONSTR_CHECK;
2792  cooked->conoid = constrOid;
2793  cooked->name = ccname;
2794  cooked->attnum = 0;
2795  cooked->expr = expr;
2796  cooked->skip_validation = cdef->skip_validation;
2797  cooked->is_local = is_local;
2798  cooked->inhcount = is_local ? 0 : 1;
2799  cooked->is_no_inherit = cdef->is_no_inherit;
2800  cookedConstraints = lappend(cookedConstraints, cooked);
2801  }
2802 
2803  /*
2804  * Update the count of constraints in the relation's pg_class tuple. We do
2805  * this even if there was no change, in order to ensure that an SI update
2806  * message is sent out for the pg_class tuple, which will force other
2807  * backends to rebuild their relcache entries for the rel. (This is
2808  * critical if we added defaults but not constraints.)
2809  */
2810  SetRelationNumChecks(rel, numchecks);
2811 
2812  return cookedConstraints;
2813 }
#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:590
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2976
bool is_no_inherit
Definition: heap.h:45
AttrNumber attnum
Definition: heap.h:29
#define RelationGetDescr(relation)
Definition: rel.h:495
#define castNode(_type_, nodeptr)
Definition: nodes.h:608
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Node * raw_expr
Definition: parsenodes.h:2249
static Node * cookConstraint(ParseState *pstate, Node *raw_constraint, char *relname)
Definition: heap.c:3134
#define AccessShareLock
Definition: lockdefs.h:36
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:539
int errcode(int sqlerrcode)
Definition: elog.c:698
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:3059
List * pull_var_clause(Node *node, int flags)
Definition: var.c:562
List * list_union(const List *list1, const List *list2)
Definition: list.c:930
char * conname
Definition: parsenodes.h:2242
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:448
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:186
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
AttrNumber attnum
Definition: heap.h:40
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:46
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:503
Node * raw_default
Definition: heap.h:30
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
bool skip_validation
Definition: heap.h:42
const char * p_sourcetext
Definition: parse_node.h:181
ConstrType contype
Definition: heap.h:37
List * lappend(List *list, void *datum)
Definition: list.c:336
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal, bool add_column_mode)
Definition: heap.c:2211
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:2826
TupleDesc rd_att
Definition: rel.h:110
uint16 num_check
Definition: tupdesc.h:43
bool is_no_inherit
Definition: parsenodes.h:2248
bool initially_valid
Definition: parsenodes.h:2285
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
Oid conoid
Definition: heap.h:38
#define NameStr(name)
Definition: c.h:681
ConstrType contype
Definition: parsenodes.h:2239
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:2250
Definition: regcomp.c:237
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
Definition: pg_list.h:50
bool skip_validation
Definition: parsenodes.h:2284
char * name
Definition: heap.h:39
#define RelationGetRelid(relation)
Definition: rel.h:469
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:2396
bool is_local
Definition: heap.h:43
#define RelationGetNamespace(relation)
Definition: rel.h:510

◆ check_nested_generated()

static void check_nested_generated ( ParseState pstate,
Node node 
)
static

Definition at line 3041 of file heap.c.

References check_nested_generated_walker().

Referenced by cookDefault().

3042 {
3043  check_nested_generated_walker(node, pstate);
3044 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:3010

◆ check_nested_generated_walker()

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

Definition at line 3010 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().

3011 {
3012  ParseState *pstate = context;
3013 
3014  if (node == NULL)
3015  return false;
3016  else if (IsA(node, Var))
3017  {
3018  Var *var = (Var *) node;
3019  Oid relid;
3021 
3022  relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
3023  attnum = var->varattno;
3024 
3025  if (OidIsValid(relid) && AttributeNumberIsValid(attnum) && get_attgenerated(relid, attnum))
3026  ereport(ERROR,
3027  (errcode(ERRCODE_SYNTAX_ERROR),
3028  errmsg("cannot use generated column \"%s\" in column generation expression",
3029  get_attname(relid, attnum, false)),
3030  errdetail("A generated column cannot reference another generated column."),
3031  parser_errposition(pstate, var->location)));
3032 
3033  return false;
3034  }
3035  else
3037  (void *) context);
3038 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:3010
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
int errcode(int sqlerrcode)
Definition: elog.c:698
AttrNumber varattno
Definition: primnodes.h:191
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:186
#define OidIsValid(objectId)
Definition: c.h:710
#define ERROR
Definition: elog.h:46
int location
Definition: primnodes.h:201
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:913
Index varno
Definition: primnodes.h:189
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
int16 attnum
Definition: pg_attribute.h:83
#define ereport(elevel,...)
Definition: elog.h:157
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1904
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:909
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:182

◆ CheckAttributeNamesTypes()

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

Definition at line 499 of file heap.c.

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

Referenced by addRangeTableEntryForFunction(), and heap_create_with_catalog().

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

◆ CheckAttributeType()

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

Definition at line 591 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().

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

◆ cookConstraint()

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

Definition at line 3134 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().

3137 {
3138  Node *expr;
3139 
3140  /*
3141  * Transform raw parsetree to executable expression.
3142  */
3143  expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
3144 
3145  /*
3146  * Make sure it yields a boolean result.
3147  */
3148  expr = coerce_to_boolean(pstate, expr, "CHECK");
3149 
3150  /*
3151  * Take care of collations.
3152  */
3153  assign_expr_collations(pstate, expr);
3154 
3155  /*
3156  * Make sure no outside relations are referred to (this is probably dead
3157  * code now that add_missing_from is history).
3158  */
3159  if (list_length(pstate->p_rtable) != 1)
3160  ereport(ERROR,
3161  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
3162  errmsg("only table \"%s\" can be referenced in check constraint",
3163  relname)));
3164 
3165  return expr;
3166 }
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:94
Definition: nodes.h:539
int errcode(int sqlerrcode)
Definition: elog.c:698
NameData relname
Definition: pg_class.h:38
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
static int list_length(const List *l)
Definition: pg_list.h:149
int errmsg(const char *fmt,...)
Definition: elog.c:909
List * p_rtable
Definition: parse_node.h:182
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 3059 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().

3065 {
3066  Node *expr;
3067 
3068  Assert(raw_default != NULL);
3069 
3070  /*
3071  * Transform raw parsetree to executable expression.
3072  */
3073  expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
3074 
3075  if (attgenerated)
3076  {
3077  check_nested_generated(pstate, expr);
3078 
3079  if (contain_mutable_functions(expr))
3080  ereport(ERROR,
3081  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3082  errmsg("generation expression is not immutable")));
3083  }
3084  else
3085  {
3086  /*
3087  * For a default expression, transformExpr() should have rejected
3088  * column references.
3089  */
3090  Assert(!contain_var_clause(expr));
3091  }
3092 
3093  /*
3094  * Coerce the expression to the correct type and typmod, if given. This
3095  * should match the parser's processing of non-defaulted expressions ---
3096  * see transformAssignedExpr().
3097  */
3098  if (OidIsValid(atttypid))
3099  {
3100  Oid type_id = exprType(expr);
3101 
3102  expr = coerce_to_target_type(pstate, expr, type_id,
3103  atttypid, atttypmod,
3106  -1);
3107  if (expr == NULL)
3108  ereport(ERROR,
3109  (errcode(ERRCODE_DATATYPE_MISMATCH),
3110  errmsg("column \"%s\" is of type %s"
3111  " but default expression is of type %s",
3112  attname,
3113  format_type_be(atttypid),
3114  format_type_be(type_id)),
3115  errhint("You will need to rewrite or cast the expression.")));
3116  }
3117 
3118  /*
3119  * Finally, take care of collations in the finished expression.
3120  */
3121  assign_expr_collations(pstate, expr);
3122 
3123  return expr;
3124 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:94
Definition: nodes.h:539
int errcode(int sqlerrcode)
Definition: elog.c:698
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
bool contain_var_clause(Node *node)
Definition: var.c:358
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ERROR
Definition: elog.h:46
NameData attname
Definition: pg_attribute.h:41
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:78
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static void check_nested_generated(ParseState *pstate, Node *node)
Definition: heap.c:3041
int errmsg(const char *fmt,...)
Definition: elog.c:909
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:359

◆ CopyStatistics()

void CopyStatistics ( Oid  fromrelid,
Oid  torelid 
)

Definition at line 3172 of file heap.c.

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

Referenced by index_concurrently_swap().

3173 {
3174  HeapTuple tup;
3175  SysScanDesc scan;
3176  ScanKeyData key[1];
3177  Relation statrel;
3178 
3179  statrel = table_open(StatisticRelationId, RowExclusiveLock);
3180 
3181  /* Now search for stat records */
3182  ScanKeyInit(&key[0],
3183  Anum_pg_statistic_starelid,
3184  BTEqualStrategyNumber, F_OIDEQ,
3185  ObjectIdGetDatum(fromrelid));
3186 
3188  true, NULL, 1, key);
3189 
3190  while (HeapTupleIsValid((tup = systable_getnext(scan))))
3191  {
3192  Form_pg_statistic statform;
3193 
3194  /* make a modifiable copy */
3195  tup = heap_copytuple(tup);
3196  statform = (Form_pg_statistic) GETSTRUCT(tup);
3197 
3198  /* update the copy of the tuple and insert it */
3199  statform->starelid = torelid;
3200  CatalogTupleInsert(statrel, tup);
3201 
3202  heap_freetuple(tup);
3203  }
3204 
3205  systable_endscan(scan);
3206 
3207  table_close(statrel, RowExclusiveLock);
3208 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
FormData_pg_statistic * Form_pg_statistic
Definition: pg_statistic.h:135
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define RowExclusiveLock
Definition: lockdefs.h:38
#define StatisticRelidAttnumInhIndexId
Definition: pg_statistic.h:140
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ DeleteAttributeTuples()

void DeleteAttributeTuples ( Oid  relid)

Definition at line 1584 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().

1585 {
1586  Relation attrel;
1587  SysScanDesc scan;
1588  ScanKeyData key[1];
1589  HeapTuple atttup;
1590 
1591  /* Grab an appropriate lock on the pg_attribute relation */
1592  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1593 
1594  /* Use the index to scan only attributes of the target relation */
1595  ScanKeyInit(&key[0],
1596  Anum_pg_attribute_attrelid,
1597  BTEqualStrategyNumber, F_OIDEQ,
1598  ObjectIdGetDatum(relid));
1599 
1600  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1601  NULL, 1, key);
1602 
1603  /* Delete all the matching tuples */
1604  while ((atttup = systable_getnext(scan)) != NULL)
1605  CatalogTupleDelete(attrel, &atttup->t_self);
1606 
1607  /* Clean up after the scan */
1608  systable_endscan(scan);
1609  table_close(attrel, RowExclusiveLock);
1610 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
ItemPointerData t_self
Definition: htup.h:65
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:208
#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 1555 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().

1556 {
1557  Relation pg_class_desc;
1558  HeapTuple tup;
1559 
1560  /* Grab an appropriate lock on the pg_class relation */
1561  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1562 
1563  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1564  if (!HeapTupleIsValid(tup))
1565  elog(ERROR, "cache lookup failed for relation %u", relid);
1566 
1567  /* delete the relation tuple from pg_class, and finish up */
1568  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1569 
1570  ReleaseSysCache(tup);
1571 
1572  table_close(pg_class_desc, RowExclusiveLock);
1573 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

Definition at line 1621 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().

1622 {
1623  Relation attrel;
1624  SysScanDesc scan;
1625  ScanKeyData key[2];
1626  HeapTuple atttup;
1627 
1628  /* Grab an appropriate lock on the pg_attribute relation */
1629  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1630 
1631  /* Use the index to scan only system attributes of the target relation */
1632  ScanKeyInit(&key[0],
1633  Anum_pg_attribute_attrelid,
1634  BTEqualStrategyNumber, F_OIDEQ,
1635  ObjectIdGetDatum(relid));
1636  ScanKeyInit(&key[1],
1637  Anum_pg_attribute_attnum,
1638  BTLessEqualStrategyNumber, F_INT2LE,
1639  Int16GetDatum(0));
1640 
1641  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1642  NULL, 2, key);
1643 
1644  /* Delete all the matching tuples */
1645  while ((atttup = systable_getnext(scan)) != NULL)
1646  CatalogTupleDelete(attrel, &atttup->t_self);
1647 
1648  /* Clean up after the scan */
1649  systable_endscan(scan);
1650  table_close(attrel, RowExclusiveLock);
1651 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define Int16GetDatum(X)
Definition: postgres.h:495
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
ItemPointerData t_self
Definition: htup.h:65
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:208
#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 295 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, recordDependencyOnTablespace(), RelationBuildLocalRelation(), RelationCreateStorage(), RelationOpenSmgr, and table_relation_set_new_filenode().

Referenced by heap_create_with_catalog(), and index_create().

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

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

References add_exact_object_address(), AddNewAttributeTuples(), AddNewRelationTuple(), AddNewRelationType(), Assert, AssignTypeArrayOid(), binary_upgrade_next_heap_pg_class_oid, binary_upgrade_next_toast_pg_class_oid, CheckAttributeNamesTypes(), CHKATYPE_ANYARRAY, CStringGetDatum, DEFAULT_TYPDELIM, DEPENDENCY_NORMAL, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errhint(), errmsg(), ERROR, free_object_addresses(), get_relname_relid(), get_user_default_acl(), GetNewRelFileNode(), GetSysCacheOid2, heap_create(), InvalidOid, InvokeObjectPostCreateHookArg, IsBinaryUpgrade, IsBootstrapProcessingMode, IsNormalProcessingMode, makeArrayTypeName(), moveArrayTypeName(), new_object_addresses(), NoLock, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum, OidIsValid, ONCOMMIT_NOOP, pfree(), PointerGetDatum, RelationData::rd_att, RelationData::rd_rel, record_object_address_dependencies(), 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().

1165 {
1166  Relation pg_class_desc;
1167  Relation new_rel_desc;
1168  Acl *relacl;
1169  Oid existing_relid;
1170  Oid old_type_oid;
1171  Oid new_type_oid;
1172  TransactionId relfrozenxid;
1173  MultiXactId relminmxid;
1174 
1175  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1176 
1177  /*
1178  * sanity checks
1179  */
1181 
1182  /*
1183  * Validate proposed tupdesc for the desired relkind. If
1184  * allow_system_table_mods is on, allow ANYARRAY to be used; this is a
1185  * hack to allow creating pg_statistic and cloning it during VACUUM FULL.
1186  */
1187  CheckAttributeNamesTypes(tupdesc, relkind,
1188  allow_system_table_mods ? CHKATYPE_ANYARRAY : 0);
1189 
1190  /*
1191  * This would fail later on anyway, if the relation already exists. But
1192  * by catching it here we can emit a nicer error message.
1193  */
1194  existing_relid = get_relname_relid(relname, relnamespace);
1195  if (existing_relid != InvalidOid)
1196  ereport(ERROR,
1197  (errcode(ERRCODE_DUPLICATE_TABLE),
1198  errmsg("relation \"%s\" already exists", relname)));
1199 
1200  /*
1201  * Since we are going to create a rowtype as well, also check for
1202  * collision with an existing type name. If there is one and it's an
1203  * autogenerated array, we can rename it out of the way; otherwise we can
1204  * at least give a good error message.
1205  */
1206  old_type_oid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
1208  ObjectIdGetDatum(relnamespace));
1209  if (OidIsValid(old_type_oid))
1210  {
1211  if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
1212  ereport(ERROR,
1214  errmsg("type \"%s\" already exists", relname),
1215  errhint("A relation has an associated type of the same name, "
1216  "so you must use a name that doesn't conflict "
1217  "with any existing type.")));
1218  }
1219 
1220  /*
1221  * Shared relations must be in pg_global (last-ditch check)
1222  */
1223  if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
1224  elog(ERROR, "shared relations must be placed in pg_global tablespace");
1225 
1226  /*
1227  * Allocate an OID for the relation, unless we were told what to use.
1228  *
1229  * The OID will be the relfilenode as well, so make sure it doesn't
1230  * collide with either pg_class OIDs or existing physical files.
1231  */
1232  if (!OidIsValid(relid))
1233  {
1234  /* Use binary-upgrade override for pg_class.oid/relfilenode? */
1235  if (IsBinaryUpgrade &&
1236  (relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
1237  relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
1238  relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE ||
1239  relkind == RELKIND_PARTITIONED_TABLE))
1240  {
1242  ereport(ERROR,
1243  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1244  errmsg("pg_class heap OID value not set when in binary upgrade mode")));
1245 
1248  }
1249  /* There might be no TOAST table, so we have to test for it. */
1250  else if (IsBinaryUpgrade &&
1252  relkind == RELKIND_TOASTVALUE)
1253  {
1256  }
1257  else
1258  relid = GetNewRelFileNode(reltablespace, pg_class_desc,
1259  relpersistence);
1260  }
1261 
1262  /*
1263  * Determine the relation's initial permissions.
1264  */
1265  if (use_user_acl)
1266  {
1267  switch (relkind)
1268  {
1269  case RELKIND_RELATION:
1270  case RELKIND_VIEW:
1271  case RELKIND_MATVIEW:
1272  case RELKIND_FOREIGN_TABLE:
1273  case RELKIND_PARTITIONED_TABLE:
1274  relacl = get_user_default_acl(OBJECT_TABLE, ownerid,
1275  relnamespace);
1276  break;
1277  case RELKIND_SEQUENCE:
1278  relacl = get_user_default_acl(OBJECT_SEQUENCE, ownerid,
1279  relnamespace);
1280  break;
1281  default:
1282  relacl = NULL;
1283  break;
1284  }
1285  }
1286  else
1287  relacl = NULL;
1288 
1289  /*
1290  * Create the relcache entry (mostly dummy at this point) and the physical
1291  * disk file. (If we fail further down, it's the smgr's responsibility to
1292  * remove the disk file again.)
1293  */
1294  new_rel_desc = heap_create(relname,
1295  relnamespace,
1296  reltablespace,
1297  relid,
1298  InvalidOid,
1299  accessmtd,
1300  tupdesc,
1301  relkind,
1302  relpersistence,
1303  shared_relation,
1304  mapped_relation,
1305  allow_system_table_mods,
1306  &relfrozenxid,
1307  &relminmxid);
1308 
1309  Assert(relid == RelationGetRelid(new_rel_desc));
1310 
1311  new_rel_desc->rd_rel->relrewrite = relrewrite;
1312 
1313  /*
1314  * Decide whether to create a pg_type entry for the relation's rowtype.
1315  * These types are made except where the use of a relation as such is an
1316  * implementation detail: toast tables, sequences and indexes.
1317  */
1318  if (!(relkind == RELKIND_SEQUENCE ||
1319  relkind == RELKIND_TOASTVALUE ||
1320  relkind == RELKIND_INDEX ||
1321  relkind == RELKIND_PARTITIONED_INDEX))
1322  {
1323  Oid new_array_oid;
1324  ObjectAddress new_type_addr;
1325  char *relarrayname;
1326 
1327  /*
1328  * We'll make an array over the composite type, too. For largely
1329  * historical reasons, the array type's OID is assigned first.
1330  */
1331  new_array_oid = AssignTypeArrayOid();
1332 
1333  /*
1334  * Make the pg_type entry for the composite type. The OID of the
1335  * composite type can be preselected by the caller, but if reltypeid
1336  * is InvalidOid, we'll generate a new OID for it.
1337  *
1338  * NOTE: we could get a unique-index failure here, in case someone
1339  * else is creating the same type name in parallel but hadn't
1340  * committed yet when we checked for a duplicate name above.
1341  */
1342  new_type_addr = AddNewRelationType(relname,
1343  relnamespace,
1344  relid,
1345  relkind,
1346  ownerid,
1347  reltypeid,
1348  new_array_oid);
1349  new_type_oid = new_type_addr.objectId;
1350  if (typaddress)
1351  *typaddress = new_type_addr;
1352 
1353  /* Now create the array type. */
1354  relarrayname = makeArrayTypeName(relname, relnamespace);
1355 
1356  TypeCreate(new_array_oid, /* force the type's OID to this */
1357  relarrayname, /* Array type name */
1358  relnamespace, /* Same namespace as parent */
1359  InvalidOid, /* Not composite, no relationOid */
1360  0, /* relkind, also N/A here */
1361  ownerid, /* owner's ID */
1362  -1, /* Internal size (varlena) */
1363  TYPTYPE_BASE, /* Not composite - typelem is */
1364  TYPCATEGORY_ARRAY, /* type-category (array) */
1365  false, /* array types are never preferred */
1366  DEFAULT_TYPDELIM, /* default array delimiter */
1367  F_ARRAY_IN, /* array input proc */
1368  F_ARRAY_OUT, /* array output proc */
1369  F_ARRAY_RECV, /* array recv (bin) proc */
1370  F_ARRAY_SEND, /* array send (bin) proc */
1371  InvalidOid, /* typmodin procedure - none */
1372  InvalidOid, /* typmodout procedure - none */
1373  F_ARRAY_TYPANALYZE, /* array analyze procedure */
1374  F_ARRAY_SUBSCRIPT_HANDLER, /* array subscript procedure */
1375  new_type_oid, /* array element type - the rowtype */
1376  true, /* yes, this is an array type */
1377  InvalidOid, /* this has no array type */
1378  InvalidOid, /* domain base type - irrelevant */
1379  NULL, /* default value - none */
1380  NULL, /* default binary representation */
1381  false, /* passed by reference */
1382  TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1383  TYPSTORAGE_EXTENDED, /* fully TOASTable */
1384  -1, /* typmod */
1385  0, /* array dimensions for typBaseType */
1386  false, /* Type NOT NULL */
1387  InvalidOid); /* rowtypes never have a collation */
1388 
1389  pfree(relarrayname);
1390  }
1391  else
1392  {
1393  /* Caller should not be expecting a type to be created. */
1394  Assert(reltypeid == InvalidOid);
1395  Assert(typaddress == NULL);
1396 
1397  new_type_oid = InvalidOid;
1398  }
1399 
1400  /*
1401  * now create an entry in pg_class for the relation.
1402  *
1403  * NOTE: we could get a unique-index failure here, in case someone else is
1404  * creating the same relation name in parallel but hadn't committed yet
1405  * when we checked for a duplicate name above.
1406  */
1407  AddNewRelationTuple(pg_class_desc,
1408  new_rel_desc,
1409  relid,
1410  new_type_oid,
1411  reloftypeid,
1412  ownerid,
1413  relkind,
1414  relfrozenxid,
1415  relminmxid,
1416  PointerGetDatum(relacl),
1417  reloptions);
1418 
1419  /*
1420  * now add tuples to pg_attribute for the attributes in our new relation.
1421  */
1422  AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind);
1423 
1424  /*
1425  * Make a dependency link to force the relation to be deleted if its
1426  * namespace is. Also make a dependency link to its owner, as well as
1427  * dependencies for any roles mentioned in the default ACL.
1428  *
1429  * For composite types, these dependencies are tracked for the pg_type
1430  * entry, so we needn't record them here. Likewise, TOAST tables don't
1431  * need a namespace dependency (they live in a pinned namespace) nor an
1432  * owner dependency (they depend indirectly through the parent table), nor
1433  * should they have any ACL entries. The same applies for extension
1434  * dependencies.
1435  *
1436  * Also, skip this in bootstrap mode, since we don't make dependencies
1437  * while bootstrapping.
1438  */
1439  if (relkind != RELKIND_COMPOSITE_TYPE &&
1440  relkind != RELKIND_TOASTVALUE &&
1442  {
1443  ObjectAddress myself,
1444  referenced;
1445  ObjectAddresses *addrs;
1446 
1447  ObjectAddressSet(myself, RelationRelationId, relid);
1448 
1449  recordDependencyOnOwner(RelationRelationId, relid, ownerid);
1450 
1451  recordDependencyOnNewAcl(RelationRelationId, relid, 0, ownerid, relacl);
1452 
1453  recordDependencyOnCurrentExtension(&myself, false);
1454 
1455  addrs = new_object_addresses();
1456 
1457  ObjectAddressSet(referenced, NamespaceRelationId, relnamespace);
1458  add_exact_object_address(&referenced, addrs);
1459 
1460  if (reloftypeid)
1461  {
1462  ObjectAddressSet(referenced, TypeRelationId, reloftypeid);
1463  add_exact_object_address(&referenced, addrs);
1464  }
1465 
1466  /*
1467  * Make a dependency link to force the relation to be deleted if its
1468  * access method is. Do this only for relation and materialized views.
1469  *
1470  * No need to add an explicit dependency for the toast table, as the
1471  * main table depends on it.
1472  */
1473  if (relkind == RELKIND_RELATION ||
1474  relkind == RELKIND_MATVIEW)
1475  {
1476  ObjectAddressSet(referenced, AccessMethodRelationId, accessmtd);
1477  add_exact_object_address(&referenced, addrs);
1478  }
1479 
1481  free_object_addresses(addrs);
1482  }
1483 
1484  /* Post creation hook for new relation */
1485  InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
1486 
1487  /*
1488  * Store any supplied constraints and defaults.
1489  *
1490  * NB: this may do a CommandCounterIncrement and rebuild the relcache
1491  * entry, so the relation must be valid and self-consistent at this point.
1492  * In particular, there are not yet constraints and defaults anywhere.
1493  */
1494  StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
1495 
1496  /*
1497  * If there's a special on-commit action, remember it
1498  */
1499  if (oncommit != ONCOMMIT_NOOP)
1500  register_on_commit_action(relid, oncommit);
1501 
1502  /*
1503  * ok, the relation has been cataloged, so close our relations and return
1504  * the OID of the newly created relation.
1505  */
1506  table_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
1507  table_close(pg_class_desc, RowExclusiveLock);
1508 
1509  return relid;
1510 }
void register_on_commit_action(Oid relid, OnCommitAction action)
Definition: tablecmds.c:16121
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:808
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int errhint(const char *fmt,...)
Definition: elog.c:1156
Oid binary_upgrade_next_heap_pg_class_oid
Definition: heap.c:93
uint32 TransactionId
Definition: c.h:587
Oid binary_upgrade_next_toast_pg_class_oid
Definition: heap.c:94
static void AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc, char relkind)
Definition: heap.c:844
#define PointerGetDatum(X)
Definition: postgres.h:600
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2701
int errcode(int sqlerrcode)
Definition: elog.c:698
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2492
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:165
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2437
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2732
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:710
bool IsBinaryUpgrade
Definition: globals.c:113
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1856
#define NoLock
Definition: lockdefs.h:34
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:848
#define IsNormalProcessingMode()
Definition: miscadmin.h:396
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
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:1066
static void StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
Definition: heap.c:2504
#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:157
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
TransactionId MultiXactId
Definition: c.h:597
#define Assert(condition)
Definition: c.h:804
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:180
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:195
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:295
ObjectAddress TypeCreate(Oid newTypeOid, const char *typeName, Oid typeNamespace, Oid relationOid, char relationKind, Oid ownerId, int16 internalSize, char typeType, char typeCategory, bool typePreferred, char typDelim, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid subscriptProcedure, Oid elementType, bool isImplicitArray, Oid arrayType, Oid baseType, const char *defaultTypeValue, char *defaultTypeBin, bool passedByValue, char alignment, char storage, int32 typeMod, int32 typNDims, bool typeNotNull, Oid typeCollation)
Definition: pg_type.c:197
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:427
Oid AssignTypeArrayOid(void)
Definition: typecmds.c:2417
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition: aclchk.c:5602
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394
#define CHKATYPE_ANYARRAY
Definition: heap.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
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:995
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, int flags)
Definition: heap.c:499
#define RelationGetRelid(relation)
Definition: rel.h:469
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:5526

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

Definition at line 1905 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().

1906 {
1907  Relation rel;
1908  HeapTuple tuple;
1909  Oid parentOid = InvalidOid,
1910  defaultPartOid = InvalidOid;
1911 
1912  /*
1913  * To drop a partition safely, we must grab exclusive lock on its parent,
1914  * because another backend might be about to execute a query on the parent
1915  * table. If it relies on previously cached partition descriptor, then it
1916  * could attempt to access the just-dropped relation as its partition. We
1917  * must therefore take a table lock strong enough to prevent all queries
1918  * on the table from proceeding until we commit and send out a
1919  * shared-cache-inval notice that will make them update their partition
1920  * descriptors.
1921  */
1922  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1923  if (!HeapTupleIsValid(tuple))
1924  elog(ERROR, "cache lookup failed for relation %u", relid);
1925  if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
1926  {
1927  /*
1928  * We have to lock the parent if the partition is being detached,
1929  * because it's possible that some query still has a partition
1930  * descriptor that includes this partition.
1931  */
1932  parentOid = get_partition_parent(relid, true);
1934 
1935  /*
1936  * If this is not the default partition, dropping it will change the
1937  * default partition's partition constraint, so we must lock it.
1938  */
1939  defaultPartOid = get_default_partition_oid(parentOid);
1940  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1941  LockRelationOid(defaultPartOid, AccessExclusiveLock);
1942  }
1943 
1944  ReleaseSysCache(tuple);
1945 
1946  /*
1947  * Open and lock the relation.
1948  */
1949  rel = relation_open(relid, AccessExclusiveLock);
1950 
1951  /*
1952  * There can no longer be anyone *else* touching the relation, but we
1953  * might still have open queries or cursors, or pending trigger events, in
1954  * our own session.
1955  */
1956  CheckTableNotInUse(rel, "DROP TABLE");
1957 
1958  /*
1959  * This effectively deletes all rows in the table, and may be done in a
1960  * serializable transaction. In that case we must record a rw-conflict in
1961  * to this transaction from each transaction holding a predicate lock on
1962  * the table.
1963  */
1965 
1966  /*
1967  * Delete pg_foreign_table tuple first.
1968  */
1969  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1970  {
1971  Relation rel;
1972  HeapTuple tuple;
1973 
1974  rel = table_open(ForeignTableRelationId, RowExclusiveLock);
1975 
1977  if (!HeapTupleIsValid(tuple))
1978  elog(ERROR, "cache lookup failed for foreign table %u", relid);
1979 
1980  CatalogTupleDelete(rel, &tuple->t_self);
1981 
1982  ReleaseSysCache(tuple);
1984  }
1985 
1986  /*
1987  * If a partitioned table, delete the pg_partitioned_table tuple.
1988  */
1989  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1991 
1992  /*
1993  * If the relation being dropped is the default partition itself,
1994  * invalidate its entry in pg_partitioned_table.
1995  */
1996  if (relid == defaultPartOid)
1998 
1999  /*
2000  * Schedule unlinking of the relation's physical files at commit.
2001  */
2002  if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
2003  RelationDropStorage(rel);
2004 
2005  /*
2006  * Close relcache entry, but *keep* AccessExclusiveLock on the relation
2007  * until transaction commit. This ensures no one else will try to do
2008  * something with the doomed relation.
2009  */
2010  relation_close(rel, NoLock);
2011 
2012  /*
2013  * Remove any associated relation synchronization states.
2014  */
2016 
2017  /*
2018  * Forget any ON COMMIT action for the rel
2019  */
2020  remove_on_commit_action(relid);
2021 
2022  /*
2023  * Flush the relation from the relcache. We want to do this before
2024  * starting to remove catalog entries, just to be certain that no relcache
2025  * entry rebuild will happen partway through. (That should not really
2026  * matter, since we don't do CommandCounterIncrement here, but let's be
2027  * safe.)
2028  */
2029  RelationForgetRelation(relid);
2030 
2031  /*
2032  * remove inheritance information
2033  */
2035 
2036  /*
2037  * delete statistics
2038  */
2039  RemoveStatistics(relid, 0);
2040 
2041  /*
2042  * delete attribute tuples
2043  */
2044  DeleteAttributeTuples(relid);
2045 
2046  /*
2047  * delete relation tuple
2048  */
2049  DeleteRelationTuple(relid);
2050 
2051  if (OidIsValid(parentOid))
2052  {
2053  /*
2054  * If this is not the default partition, the partition constraint of
2055  * the default partition has changed to include the portion of the key
2056  * space previously covered by the dropped partition.
2057  */
2058  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
2059  CacheInvalidateRelcacheByRelid(defaultPartOid);
2060 
2061  /*
2062  * Invalidate the parent's relcache so that the partition is no longer
2063  * included in its partition descriptor.
2064  */
2065  CacheInvalidateRelcacheByRelid(parentOid);
2066  /* keep the lock */
2067  }
2068 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
void RemoveSubscriptionRel(Oid subid, Oid relid)
Oid get_partition_parent(Oid relid, bool even_if_detached)
Definition: partition.c:54
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:338
void remove_on_commit_action(Oid relid)
Definition: tablecmds.c:16157
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2750
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
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
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1337
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3929
Oid get_default_partition_oid(Oid parentId)
Definition: partition.c:313
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void RelationDropStorage(Relation rel)
Definition: storage.c:195
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define InvalidOid
Definition: postgres_ext.h:36
void DeleteRelationTuple(Oid relid)
Definition: heap.c:1555
#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:1522
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4529
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1584
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:3217
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define AccessExclusiveLock
Definition: lockdefs.h:45
void RemovePartitionKeyByRelId(Oid relid)
Definition: heap.c:3747
#define elog(elevel,...)
Definition: elog.h:232
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ heap_truncate()

void heap_truncate ( List relids)

Definition at line 3312 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().

3313 {
3314  List *relations = NIL;
3315  ListCell *cell;
3316 
3317  /* Open relations for processing, and grab exclusive access on each */
3318  foreach(cell, relids)
3319  {
3320  Oid rid = lfirst_oid(cell);
3321  Relation rel;
3322 
3323  rel = table_open(rid, AccessExclusiveLock);
3324  relations = lappend(relations, rel);
3325  }
3326 
3327  /* Don't allow truncate on tables that are referenced by foreign keys */
3328  heap_truncate_check_FKs(relations, true);
3329 
3330  /* OK to do it */
3331  foreach(cell, relations)
3332  {
3333  Relation rel = lfirst(cell);
3334 
3335  /* Truncate the relation */
3336  heap_truncate_one_rel(rel);
3337 
3338  /* Close the relation, but keep exclusive lock on it until commit */
3339  table_close(rel, NoLock);
3340  }
3341 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:3353
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3397
unsigned int Oid
Definition: postgres_ext.h:31
#define NoLock
Definition: lockdefs.h:34
List * lappend(List *list, void *datum)
Definition: list.c:336
#define lfirst(lc)
Definition: pg_list.h:169
#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:171

◆ heap_truncate_check_FKs()

void heap_truncate_check_FKs ( List relations,
bool  tempTables 
)

Definition at line 3397 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().

3398 {
3399  List *oids = NIL;
3400  List *dependents;
3401  ListCell *cell;
3402 
3403  /*
3404  * Build a list of OIDs of the interesting relations.
3405  *
3406  * If a relation has no triggers, then it can neither have FKs nor be
3407  * referenced by a FK from another table, so we can ignore it. For
3408  * partitioned tables, FKs have no triggers, so we must include them
3409  * anyway.
3410  */
3411  foreach(cell, relations)
3412  {
3413  Relation rel = lfirst(cell);
3414 
3415  if (rel->rd_rel->relhastriggers ||
3416  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3417  oids = lappend_oid(oids, RelationGetRelid(rel));
3418  }
3419 
3420  /*
3421  * Fast path: if no relation has triggers, none has FKs either.
3422  */
3423  if (oids == NIL)
3424  return;
3425 
3426  /*
3427  * Otherwise, must scan pg_constraint. We make one pass with all the
3428  * relations considered; if this finds nothing, then all is well.
3429  */
3430  dependents = heap_truncate_find_FKs(oids);
3431  if (dependents == NIL)
3432  return;
3433 
3434  /*
3435  * Otherwise we repeat the scan once per relation to identify a particular
3436  * pair of relations to complain about. This is pretty slow, but
3437  * performance shouldn't matter much in a failure path. The reason for
3438  * doing things this way is to ensure that the message produced is not
3439  * dependent on chance row locations within pg_constraint.
3440  */
3441  foreach(cell, oids)
3442  {
3443  Oid relid = lfirst_oid(cell);
3444  ListCell *cell2;
3445 
3446  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
3447 
3448  foreach(cell2, dependents)
3449  {
3450  Oid relid2 = lfirst_oid(cell2);
3451 
3452  if (!list_member_oid(oids, relid2))
3453  {
3454  char *relname = get_rel_name(relid);
3455  char *relname2 = get_rel_name(relid2);
3456 
3457  if (tempTables)
3458  ereport(ERROR,
3459  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3460  errmsg("unsupported ON COMMIT and foreign key combination"),
3461  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3462  relname2, relname)));
3463  else
3464  ereport(ERROR,
3465  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3466  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3467  errdetail("Table \"%s\" references \"%s\".",
3468  relname2, relname),
3469  errhint("Truncate table \"%s\" at the same time, "
3470  "or use TRUNCATE ... CASCADE.",
3471  relname2)));
3472  }
3473  }
3474  }
3475 }
#define NIL
Definition: pg_list.h:65
int errhint(const char *fmt,...)
Definition: elog.c:1156
int errcode(int sqlerrcode)
Definition: elog.c:698
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:372
#define ERROR
Definition: elog.h:46
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define list_make1_oid(x1)
Definition: pg_list.h:236
#define ereport(elevel,...)
Definition: elog.h:157
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:689
#define lfirst(lc)
Definition: pg_list.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: pg_list.h:50
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1899
#define RelationGetRelid(relation)
Definition: rel.h:469
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3492
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

Definition at line 3492 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().

3493 {
3494  List *result = NIL;
3495  List *oids;
3496  List *parent_cons;
3497  ListCell *cell;
3498  ScanKeyData key;
3499  Relation fkeyRel;
3500  SysScanDesc fkeyScan;
3501  HeapTuple tuple;
3502  bool restart;
3503 
3504  oids = list_copy(relationIds);
3505 
3506  /*
3507  * Must scan pg_constraint. Right now, it is a seqscan because there is
3508  * no available index on confrelid.
3509  */
3510  fkeyRel = table_open(ConstraintRelationId, AccessShareLock);
3511 
3512 restart:
3513  restart = false;
3514  parent_cons = NIL;
3515 
3516  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3517  NULL, 0, NULL);
3518 
3519  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3520  {
3522 
3523  /* Not a foreign key */
3524  if (con->contype != CONSTRAINT_FOREIGN)
3525  continue;
3526 
3527  /* Not referencing one of our list of tables */
3528  if (!list_member_oid(oids, con->confrelid))
3529  continue;
3530 
3531  /*
3532  * If this constraint has a parent constraint which we have not seen
3533  * yet, keep track of it for the second loop, below. Tracking parent
3534  * constraints allows us to climb up to the top-level level constraint
3535  * and look for all possible relations referencing the partitioned
3536  * table.
3537  */
3538  if (OidIsValid(con->conparentid) &&
3539  !list_member_oid(parent_cons, con->conparentid))
3540  parent_cons = lappend_oid(parent_cons, con->conparentid);
3541 
3542  /*
3543  * Add referencer to result, unless present in input list. (Don't
3544  * worry about dupes: we'll fix that below).
3545  */
3546  if (!list_member_oid(relationIds, con->conrelid))
3547  result = lappend_oid(result, con->conrelid);
3548  }
3549 
3550  systable_endscan(fkeyScan);
3551 
3552  /*
3553  * Process each parent constraint we found to add the list of referenced
3554  * relations by them to the oids list. If we do add any new such
3555  * relations, redo the first loop above. Also, if we see that the parent
3556  * constraint in turn has a parent, add that so that we process all
3557  * relations in a single additional pass.
3558  */
3559  foreach(cell, parent_cons)
3560  {
3561  Oid parent = lfirst_oid(cell);
3562 
3563  ScanKeyInit(&key,
3564  Anum_pg_constraint_oid,
3565  BTEqualStrategyNumber, F_OIDEQ,
3566  ObjectIdGetDatum(parent));
3567 
3568  fkeyScan = systable_beginscan(fkeyRel, ConstraintOidIndexId,
3569  true, NULL, 1, &key);
3570 
3571  tuple = systable_getnext(fkeyScan);
3572  if (HeapTupleIsValid(tuple))
3573  {
3575 
3576  /*
3577  * pg_constraint rows always appear for partitioned hierarchies
3578  * this way: on the each side of the constraint, one row appears
3579  * for each partition that points to the top-most table on the
3580  * other side.
3581  *
3582  * Because of this arrangement, we can correctly catch all
3583  * relevant relations by adding to 'parent_cons' all rows with
3584  * valid conparentid, and to the 'oids' list all rows with a zero
3585  * conparentid. If any oids are added to 'oids', redo the first
3586  * loop above by setting 'restart'.
3587  */
3588  if (OidIsValid(con->conparentid))
3589  parent_cons = list_append_unique_oid(parent_cons,
3590  con->conparentid);
3591  else if (!list_member_oid(oids, con->confrelid))
3592  {
3593  oids = lappend_oid(oids, con->confrelid);
3594  restart = true;
3595  }
3596  }
3597 
3598  systable_endscan(fkeyScan);
3599  }
3600 
3601  list_free(parent_cons);
3602  if (restart)
3603  goto restart;
3604 
3605  table_close(fkeyRel, AccessShareLock);
3606  list_free(oids);
3607 
3608  /* Now sort and de-duplicate the result list */
3609  list_sort(result, list_oid_cmp);
3610  list_deduplicate_oid(result);
3611 
3612  return result;
3613 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
List * list_append_unique_oid(List *list, Oid datum)
Definition: list.c:1232
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define AccessShareLock
Definition: lockdefs.h:36
List * list_copy(const List *oldlist)
Definition: list.c:1418
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define OidIsValid(objectId)
Definition: c.h:710
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1529
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ConstraintOidIndexId
void list_deduplicate_oid(List *list)
Definition: list.c:1340
#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:689
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1496
void list_free(List *list)
Definition: list.c:1391
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:171

◆ heap_truncate_one_rel()

void heap_truncate_one_rel ( Relation  rel)

Definition at line 3353 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().

3354 {
3355  Oid toastrelid;
3356 
3357  /*
3358  * Truncate the relation. Partitioned tables have no storage, so there is
3359  * nothing to do for them here.
3360  */
3361  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3362  return;
3363 
3364  /* Truncate the underlying relation */
3366 
3367  /* If the relation has indexes, truncate the indexes too */
3369 
3370  /* If there is a toast table, truncate that too */
3371  toastrelid = rel->rd_rel->reltoastrelid;
3372  if (OidIsValid(toastrelid))
3373  {
3374  Relation toastrel = table_open(toastrelid, AccessExclusiveLock);
3375 
3377  RelationTruncateIndexes(toastrel);
3378  /* keep the lock... */
3379  table_close(toastrel, NoLock);
3380  }
3381 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
static void table_relation_nontransactional_truncate(Relation rel)
Definition: tableam.h:1607
#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:3264

◆ InsertPgAttributeTuples()

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

Definition at line 740 of file heap.c.

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

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

745 {
746  TupleTableSlot **slot;
747  TupleDesc td;
748  int nslots;
749  int natts = 0;
750  int slotCount = 0;
751  bool close_index = false;
752 
753  td = RelationGetDescr(pg_attribute_rel);
754 
755  /* Initialize the number of slots to use */
756  nslots = Min(tupdesc->natts,
758  slot = palloc(sizeof(TupleTableSlot *) * nslots);
759  for (int i = 0; i < nslots; i++)
761 
762  while (natts < tupdesc->natts)
763  {
764  Form_pg_attribute attrs = TupleDescAttr(tupdesc, natts);
765 
766  ExecClearTuple(slot[slotCount]);
767 
768  if (new_rel_oid != InvalidOid)
769  slot[slotCount]->tts_values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_rel_oid);
770  else
771  slot[slotCount]->tts_values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(attrs->attrelid);
772 
773  slot[slotCount]->tts_values[Anum_pg_attribute_attname - 1] = NameGetDatum(&attrs->attname);
774  slot[slotCount]->tts_values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(attrs->atttypid);
775  slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(attrs->attstattarget);
776  slot[slotCount]->tts_values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(attrs->attlen);
777  slot[slotCount]->tts_values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(attrs->attnum);
778  slot[slotCount]->tts_values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(attrs->attndims);
779  slot[slotCount]->tts_values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
780  slot[slotCount]->tts_values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(attrs->atttypmod);
781  slot[slotCount]->tts_values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(attrs->attbyval);
782  slot[slotCount]->tts_values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(attrs->attstorage);
783  slot[slotCount]->tts_values[Anum_pg_attribute_attalign - 1] = CharGetDatum(attrs->attalign);
784  slot[slotCount]->tts_values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(attrs->attnotnull);
785  slot[slotCount]->tts_values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(attrs->atthasdef);
786  slot[slotCount]->tts_values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(attrs->atthasmissing);
787  slot[slotCount]->tts_values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(attrs->attidentity);
788  slot[slotCount]->tts_values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(attrs->attgenerated);
789  slot[slotCount]->tts_values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(attrs->attisdropped);
790  slot[slotCount]->tts_values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(attrs->attislocal);
791  slot[slotCount]->tts_values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(attrs->attinhcount);
792  slot[slotCount]->tts_values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(attrs->attcollation);
793  slot[slotCount]->tts_values[Anum_pg_attribute_attcompression - 1] = CharGetDatum(attrs->attcompression);
794  if (attoptions && attoptions[natts] != (Datum) 0)
795  slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attoptions[natts];
796  else
797  slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = true;
798 
799  /* start out with empty permissions and empty options */
800  slot[slotCount]->tts_isnull[Anum_pg_attribute_attacl - 1] = true;
801  slot[slotCount]->tts_isnull[Anum_pg_attribute_attfdwoptions - 1] = true;
802  slot[slotCount]->tts_isnull[Anum_pg_attribute_attmissingval - 1] = true;
803 
804  ExecStoreVirtualTuple(slot[slotCount]);
805  slotCount++;
806 
807  /*
808  * If slots are full or the end of processing has been reached, insert
809  * a batch of tuples.
810  */
811  if (slotCount == nslots || natts == tupdesc->natts - 1)
812  {
813  /* fetch index info only when we know we need it */
814  if (!indstate)
815  {
816  indstate = CatalogOpenIndexes(pg_attribute_rel);
817  close_index = true;
818  }
819 
820  /* insert the new tuples and update the indexes */
821  CatalogTuplesMultiInsertWithInfo(pg_attribute_rel, slot, slotCount,
822  indstate);
823  slotCount = 0;
824  }
825 
826  natts++;
827  }
828 
829  if (close_index)
830  CatalogCloseIndexes(indstate);
831  for (int i = 0; i < nslots; i++)
833  pfree(slot);
834 }
#define NameGetDatum(X)
Definition: postgres.h:639
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
#define RelationGetDescr(relation)
Definition: rel.h:495
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1238
#define MAX_CATALOG_MULTI_INSERT_BYTES
Definition: indexing.h:33
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define Min(x, y)
Definition: c.h:986
#define Int16GetDatum(X)
Definition: postgres.h:495
Datum * tts_values
Definition: tuptable.h:126
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
void CatalogTuplesMultiInsertWithInfo(Relation heapRel, TupleTableSlot **slot, int ntuples, CatalogIndexState indstate)
Definition: indexing.c:261
bool * tts_isnull
Definition: tuptable.h:128
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1254
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define InvalidOid
Definition: postgres_ext.h:36
FormData_pg_attribute
Definition: pg_attribute.h:187
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:43
#define CharGetDatum(X)
Definition: postgres.h:460
#define Int32GetDatum(X)
Definition: postgres.h:523
void * palloc(Size size)
Definition: mcxt.c:1062
int i
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:84
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:61
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1552

◆ InsertPgClassTuple()

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

Definition at line 922 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().

927 {
928  Form_pg_class rd_rel = new_rel_desc->rd_rel;
929  Datum values[Natts_pg_class];
930  bool nulls[Natts_pg_class];
931  HeapTuple tup;
932 
933  /* This is a tad tedious, but way cleaner than what we used to do... */
934  memset(values, 0, sizeof(values));
935  memset(nulls, false, sizeof(nulls));
936 
937  values[Anum_pg_class_oid - 1] = ObjectIdGetDatum(new_rel_oid);
938  values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
939  values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
940  values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
941  values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
942  values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
943  values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
944  values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
945  values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
946  values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
947  values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
948  values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
949  values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
950  values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
951  values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
952  values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
953  values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
954  values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
955  values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
956  values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
957  values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
958  values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
959  values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
960  values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
961  values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
962  values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
963  values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
964  values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite);
965  values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
966  values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
967  if (relacl != (Datum) 0)
968  values[Anum_pg_class_relacl - 1] = relacl;
969  else
970  nulls[Anum_pg_class_relacl - 1] = true;
971  if (reloptions != (Datum) 0)
972  values[Anum_pg_class_reloptions - 1] = reloptions;
973  else
974  nulls[Anum_pg_class_reloptions - 1] = true;
975 
976  /* relpartbound is set by updating this tuple, if necessary */
977  nulls[Anum_pg_class_relpartbound - 1] = true;
978 
979  tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
980 
981  /* finally insert the new tuple, update the indexes, and clean up */
982  CatalogTupleInsert(pg_class_desc, tup);
983 
984  heap_freetuple(tup);
985 }
static Datum Float4GetDatum(float4 X)
Definition: postgres.h:725
#define NameGetDatum(X)
Definition: postgres.h:639
#define MultiXactIdGetDatum(X)
Definition: postgres.h:572
#define RelationGetDescr(relation)
Definition: rel.h:495
#define Int16GetDatum(X)
Definition: postgres.h:495
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:551
#define TransactionIdGetDatum(X)
Definition: postgres.h:565
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define CharGetDatum(X)
Definition: postgres.h:460
static Datum values[MAXATTR]
Definition: bootstrap.c:166
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define Int32GetDatum(X)
Definition: postgres.h:523
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

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

2830 {
2831  bool found;
2832  Relation conDesc;
2833  SysScanDesc conscan;
2834  ScanKeyData skey[3];
2835  HeapTuple tup;
2836 
2837  /* Search for a pg_constraint entry with same name and relation */
2838  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
2839 
2840  found = false;
2841 
2842  ScanKeyInit(&skey[0],
2843  Anum_pg_constraint_conrelid,
2844  BTEqualStrategyNumber, F_OIDEQ,
2846  ScanKeyInit(&skey[1],
2847  Anum_pg_constraint_contypid,
2848  BTEqualStrategyNumber, F_OIDEQ,
2850  ScanKeyInit(&skey[2],
2851  Anum_pg_constraint_conname,
2852  BTEqualStrategyNumber, F_NAMEEQ,
2853  CStringGetDatum(ccname));
2854 
2855  conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId, true,
2856  NULL, 3, skey);
2857 
2858  /* There can be at most one matching row */
2859  if (HeapTupleIsValid(tup = systable_getnext(conscan)))
2860  {
2862 
2863  /* Found it. Conflicts if not identical check constraint */
2864  if (con->contype == CONSTRAINT_CHECK)
2865  {
2866  Datum val;
2867  bool isnull;
2868 
2869  val = fastgetattr(tup,
2870  Anum_pg_constraint_conbin,
2871  conDesc->rd_att, &isnull);
2872  if (isnull)
2873  elog(ERROR, "null conbin for rel %s",
2875  if (equal(expr, stringToNode(TextDatumGetCString(val))))
2876  found = true;
2877  }
2878 
2879  /*
2880  * If the existing constraint is purely inherited (no local
2881  * definition) then interpret addition of a local constraint as a
2882  * legal merge. This allows ALTER ADD CONSTRAINT on parent and child
2883  * tables to be given in either order with same end state. However if
2884  * the relation is a partition, all inherited constraints are always
2885  * non-local, including those that were merged.
2886  */
2887  if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
2888  allow_merge = true;
2889 
2890  if (!found || !allow_merge)
2891  ereport(ERROR,
2893  errmsg("constraint \"%s\" for relation \"%s\" already exists",
2894  ccname, RelationGetRelationName(rel))));
2895 
2896  /* If the child constraint is "no inherit" then cannot merge */
2897  if (con->connoinherit)
2898  ereport(ERROR,
2899  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2900  errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
2901  ccname, RelationGetRelationName(rel))));
2902 
2903  /*
2904  * Must not change an existing inherited constraint to "no inherit"
2905  * status. That's because inherited constraints should be able to
2906  * propagate to lower-level children.
2907  */
2908  if (con->coninhcount > 0 && is_no_inherit)
2909  ereport(ERROR,
2910  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2911  errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
2912  ccname, RelationGetRelationName(rel))));
2913 
2914  /*
2915  * If the child constraint is "not valid" then cannot merge with a
2916  * valid parent constraint.
2917  */
2918  if (is_initially_valid && !con->convalidated)
2919  ereport(ERROR,
2920  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2921  errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
2922  ccname, RelationGetRelationName(rel))));
2923 
2924  /* OK to update the tuple */
2925  ereport(NOTICE,
2926  (errmsg("merging constraint \"%s\" with inherited definition",
2927  ccname)));
2928 
2929  tup = heap_copytuple(tup);
2930  con = (Form_pg_constraint) GETSTRUCT(tup);
2931 
2932  /*
2933  * In case of partitions, an inherited constraint must be inherited
2934  * only once since it cannot have multiple parents and it is never
2935  * considered local.
2936  */
2937  if (rel->rd_rel->relispartition)
2938  {
2939  con->coninhcount = 1;
2940  con->conislocal = false;
2941  }
2942  else
2943  {
2944  if (is_local)
2945  con->conislocal = true;
2946  else
2947  con->coninhcount++;
2948  }
2949 
2950  if (is_no_inherit)
2951  {
2952  Assert(is_local);
2953  con->connoinherit = true;
2954  }
2955 
2956  CatalogTupleUpdate(conDesc, &tup->t_self, tup);
2957  }
2958 
2959  systable_endscan(conscan);
2960  table_close(conDesc, RowExclusiveLock);
2961 
2962  return found;
2963 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:711
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3113
int errcode(int sqlerrcode)
Definition: elog.c:698
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:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define ConstraintRelidTypidNameIndexId
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
#define RelationGetRelationName(relation)
Definition: rel.h:503
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#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:804
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
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:32
#define RelationGetRelid(relation)
Definition: rel.h:469
long val
Definition: informix.c:664
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RelationClearMissing()

void RelationClearMissing ( Relation  rel)

Definition at line 2082 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().

2083 {
2084  Relation attr_rel;
2085  Oid relid = RelationGetRelid(rel);
2086  int natts = RelationGetNumberOfAttributes(rel);
2087  int attnum;
2088  Datum repl_val[Natts_pg_attribute];
2089  bool repl_null[Natts_pg_attribute];
2090  bool repl_repl[Natts_pg_attribute];
2091  Form_pg_attribute attrtuple;
2092  HeapTuple tuple,
2093  newtuple;
2094 
2095  memset(repl_val, 0, sizeof(repl_val));
2096  memset(repl_null, false, sizeof(repl_null));
2097  memset(repl_repl, false, sizeof(repl_repl));
2098 
2099  repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
2100  repl_null[Anum_pg_attribute_attmissingval - 1] = true;
2101 
2102  repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
2103  repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
2104 
2105 
2106  /* Get a lock on pg_attribute */
2107  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
2108 
2109  /* process each non-system attribute, including any dropped columns */
2110  for (attnum = 1; attnum <= natts; attnum++)
2111  {
2112  tuple = SearchSysCache2(ATTNUM,
2113  ObjectIdGetDatum(relid),
2114  Int16GetDatum(attnum));
2115  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
2116  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2117  attnum, relid);
2118 
2119  attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
2120 
2121  /* ignore any where atthasmissing is not true */
2122  if (attrtuple->atthasmissing)
2123  {
2124  newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
2125  repl_val, repl_null, repl_repl);
2126 
2127  CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
2128 
2129  heap_freetuple(newtuple);
2130  }
2131 
2132  ReleaseSysCache(tuple);
2133  }
2134 
2135  /*
2136  * Our update of the pg_attribute rows will force a relcache rebuild, so
2137  * there's nothing else to do here.
2138  */
2139  table_close(attr_rel, RowExclusiveLock);
2140 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:495
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:475
#define Int16GetDatum(X)
Definition: postgres.h:495
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define BoolGetDatum(X)
Definition: postgres.h:446
int16 attnum
Definition: pg_attribute.h:83
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
#define elog(elevel,...)
Definition: elog.h:232
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:469

◆ RelationRemoveInheritance()

static void RelationRemoveInheritance ( Oid  relid)
static

Definition at line 1522 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().

1523 {
1524  Relation catalogRelation;
1525  SysScanDesc scan;
1526  ScanKeyData key;
1527  HeapTuple tuple;
1528 
1529  catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
1530 
1531  ScanKeyInit(&key,
1532  Anum_pg_inherits_inhrelid,
1533  BTEqualStrategyNumber, F_OIDEQ,
1534  ObjectIdGetDatum(relid));
1535 
1536  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
1537  NULL, 1, &key);
1538 
1539  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1540  CatalogTupleDelete(catalogRelation, &tuple->t_self);
1541 
1542  systable_endscan(scan);
1543  table_close(catalogRelation, RowExclusiveLock);
1544 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define InheritsRelidSeqnoIndexId
Definition: pg_inherits.h:48
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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 3264 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().

3265 {
3266  ListCell *indlist;
3267 
3268  /* Ask the relcache to produce a list of the indexes of the rel */
3269  foreach(indlist, RelationGetIndexList(heapRelation))
3270  {
3271  Oid indexId = lfirst_oid(indlist);
3272  Relation currentIndex;
3273  IndexInfo *indexInfo;
3274 
3275  /* Open the index relation; use exclusive lock, just to be sure */
3276  currentIndex = index_open(indexId, AccessExclusiveLock);
3277 
3278  /*
3279  * Fetch info needed for index_build. Since we know there are no
3280  * tuples that actually need indexing, we can use a dummy IndexInfo.
3281  * This is slightly cheaper to build, but the real point is to avoid
3282  * possibly running user-defined code in index expressions or
3283  * predicates. We might be getting invoked during ON COMMIT
3284  * processing, and we don't want to run any such code then.
3285  */
3286  indexInfo = BuildDummyIndexInfo(currentIndex);
3287 
3288  /*
3289  * Now truncate the actual file (and discard buffers).
3290  */
3291  RelationTruncate(currentIndex, 0);
3292 
3293  /* Initialize the index and rebuild */
3294  /* Note: we do not need to re-establish pkey setting */
3295  index_build(heapRelation, currentIndex, indexInfo, true, false);
3296 
3297  /* We're done with this index */
3298  index_close(currentIndex, NoLock);
3299  }
3300 }
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:2896
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4570
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
#define AccessExclusiveLock
Definition: lockdefs.h:45
IndexInfo * BuildDummyIndexInfo(Relation index)
Definition: index.c:2435
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
#define lfirst_oid(lc)
Definition: pg_list.h:171
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 1777 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(), ATExecCookedColumnDefault(), and ATExecDropExpression().

1779 {
1780  Relation attrdef_rel;
1781  ScanKeyData scankeys[2];
1782  SysScanDesc scan;
1783  HeapTuple tuple;
1784  bool found = false;
1785 
1786  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1787 
1788  ScanKeyInit(&scankeys[0],
1789  Anum_pg_attrdef_adrelid,
1790  BTEqualStrategyNumber, F_OIDEQ,
1791  ObjectIdGetDatum(relid));
1792  ScanKeyInit(&scankeys[1],
1793  Anum_pg_attrdef_adnum,
1794  BTEqualStrategyNumber, F_INT2EQ,
1796 
1797  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1798  NULL, 2, scankeys);
1799 
1800  /* There should be at most one matching tuple, but we loop anyway */
1801  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1802  {
1803  ObjectAddress object;
1804  Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
1805 
1806  object.classId = AttrDefaultRelationId;
1807  object.objectId = attrtuple->oid;
1808  object.objectSubId = 0;
1809 
1810  performDeletion(&object, behavior,
1811  internal ? PERFORM_DELETION_INTERNAL : 0);
1812 
1813  found = true;
1814  }
1815 
1816  systable_endscan(scan);
1817  table_close(attrdef_rel, RowExclusiveLock);
1818 
1819  if (complain && !found)
1820  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1821  relid, attnum);
1822 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define AttrDefaultIndexId
Definition: pg_attrdef.h:53
#define Int16GetDatum(X)
Definition: postgres.h:495
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#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:48
int16 attnum
Definition: pg_attribute.h:83
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232
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:141

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

Definition at line 1832 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().

1833 {
1834  Relation attrdef_rel;
1835  Relation attr_rel;
1836  Relation myrel;
1837  ScanKeyData scankeys[1];
1838  SysScanDesc scan;
1839  HeapTuple tuple;
1840  Oid myrelid;
1841  AttrNumber myattnum;
1842 
1843  /* Grab an appropriate lock on the pg_attrdef relation */
1844  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1845 
1846  /* Find the pg_attrdef tuple */
1847  ScanKeyInit(&scankeys[0],
1848  Anum_pg_attrdef_oid,
1849  BTEqualStrategyNumber, F_OIDEQ,
1850  ObjectIdGetDatum(attrdefId));
1851 
1852  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1853  NULL, 1, scankeys);
1854 
1855  tuple = systable_getnext(scan);
1856  if (!HeapTupleIsValid(tuple))
1857  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1858 
1859  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1860  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1861 
1862  /* Get an exclusive lock on the relation owning the attribute */
1863  myrel = relation_open(myrelid, AccessExclusiveLock);
1864 
1865  /* Now we can delete the pg_attrdef row */
1866  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1867 
1868  systable_endscan(scan);
1869  table_close(attrdef_rel, RowExclusiveLock);
1870 
1871  /* Fix the pg_attribute row */
1872  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1873 
1874  tuple = SearchSysCacheCopy2(ATTNUM,
1875  ObjectIdGetDatum(myrelid),
1876  Int16GetDatum(myattnum));
1877  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1878  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1879  myattnum, myrelid);
1880 
1881  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1882 
1883  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1884 
1885  /*
1886  * Our update of the pg_attribute row will force a relcache rebuild, so
1887  * there's nothing else to do here.
1888  */
1889  table_close(attr_rel, RowExclusiveLock);
1890 
1891  /* Keep lock on attribute's rel until end of xact */
1892  relation_close(myrel, NoLock);
1893 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define Int16GetDatum(X)
Definition: postgres.h:495
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
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:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
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:203
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:48
#define AttrDefaultOidIndexId
Definition: pg_attrdef.h:55
#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:301
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define elog(elevel,...)
Definition: elog.h:232
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:177
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 1662 of file heap.c.

References AccessExclusiveLock, ATTNUM, BoolGetDatum, CatalogTupleDelete(), CatalogTupleUpdate(), elog, ERROR, GETSTRUCT, heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum, InvalidCompressionMethod, 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().

1663 {
1664  Relation rel;
1665  Relation attr_rel;
1666  HeapTuple tuple;
1667  Form_pg_attribute attStruct;
1668  char newattname[NAMEDATALEN];
1669 
1670  /*
1671  * Grab an exclusive lock on the target table, which we will NOT release
1672  * until end of transaction. (In the simple case where we are directly
1673  * dropping this column, ATExecDropColumn already did this ... but when
1674  * cascading from a drop of some other object, we may not have any lock.)
1675  */
1676  rel = relation_open(relid, AccessExclusiveLock);
1677 
1678  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1679 
1680  tuple = SearchSysCacheCopy2(ATTNUM,
1681  ObjectIdGetDatum(relid),
1683  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1684  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1685  attnum, relid);
1686  attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
1687 
1688  if (attnum < 0)
1689  {
1690  /* System attribute (probably OID) ... just delete the row */
1691 
1692  CatalogTupleDelete(attr_rel, &tuple->t_self);
1693  }
1694  else
1695  {
1696  /* Dropping user attributes is lots harder */
1697 
1698  /* Mark the attribute as dropped */
1699  attStruct->attisdropped = true;
1700 
1701  /*
1702  * Set the type OID to invalid. A dropped attribute's type link
1703  * cannot be relied on (once the attribute is dropped, the type might
1704  * be too). Fortunately we do not need the type row --- the only
1705  * really essential information is the type's typlen and typalign,
1706  * which are preserved in the attribute's attlen and attalign. We set
1707  * atttypid to zero here as a means of catching code that incorrectly
1708  * expects it to be valid.
1709  */
1710  attStruct->atttypid = InvalidOid;
1711 
1712  /* Remove any NOT NULL constraint the column may have */
1713  attStruct->attnotnull = false;
1714 
1715  /* We don't want to keep stats for it anymore */
1716  attStruct->attstattarget = 0;
1717 
1718  /* Unset this so no one tries to look up the generation expression */
1719  attStruct->attgenerated = '\0';
1720 
1721  attStruct->attcompression = InvalidCompressionMethod;
1722 
1723  /*
1724  * Change the column name to something that isn't likely to conflict
1725  */
1726  snprintf(newattname, sizeof(newattname),
1727  "........pg.dropped.%d........", attnum);
1728  namestrcpy(&(attStruct->attname), newattname);
1729 
1730  /* clear the missing value if any */
1731  if (attStruct->atthasmissing)
1732  {
1733  Datum valuesAtt[Natts_pg_attribute];
1734  bool nullsAtt[Natts_pg_attribute];
1735  bool replacesAtt[Natts_pg_attribute];
1736 
1737  /* update the tuple - set atthasmissing and attmissingval */
1738  MemSet(valuesAtt, 0, sizeof(valuesAtt));
1739  MemSet(nullsAtt, false, sizeof(nullsAtt));
1740  MemSet(replacesAtt, false, sizeof(replacesAtt));
1741 
1742  valuesAtt[Anum_pg_attribute_atthasmissing - 1] =
1743  BoolGetDatum(false);
1744  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
1745  valuesAtt[Anum_pg_attribute_attmissingval - 1] = (Datum) 0;
1746  nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
1747  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
1748 
1749  tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
1750  valuesAtt, nullsAtt, replacesAtt);
1751  }
1752 
1753  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1754  }
1755 
1756  /*
1757  * Because updating the pg_attribute row will trigger a relcache flush for
1758  * the target relation, we need not do anything else to notify other
1759  * backends of the change.
1760  */
1761 
1762  table_close(attr_rel, RowExclusiveLock);
1763 
1764  if (attnum > 0)
1765  RemoveStatistics(relid, attnum);
1766 
1767  relation_close(rel, NoLock);
1768 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:495
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define Int16GetDatum(X)
Definition: postgres.h:495
#define MemSet(start, val, len)
Definition: c.h:1008
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
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:203
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define InvalidOid
Definition: postgres_ext.h:36
int16 attnum
Definition: pg_attribute.h:83
#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:301
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:3217
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define InvalidCompressionMethod
#define elog(elevel,...)
Definition: elog.h:232
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:177
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:216

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

Definition at line 3747 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().

3748 {
3749  Relation rel;
3750  HeapTuple tuple;
3751 
3752  rel = table_open(PartitionedRelationId, RowExclusiveLock);
3753 
3754  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3755  if (!HeapTupleIsValid(tuple))
3756  elog(ERROR, "cache lookup failed for partition key of relation %u",
3757  relid);
3758 
3759  CatalogTupleDelete(rel, &tuple->t_self);
3760 
3761  ReleaseSysCache(tuple);
3763 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 3217 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().

3218 {
3219  Relation pgstatistic;
3220  SysScanDesc scan;
3221  ScanKeyData key[2];
3222  int nkeys;
3223  HeapTuple tuple;
3224 
3225  pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
3226 
3227  ScanKeyInit(&key[0],
3228  Anum_pg_statistic_starelid,
3229  BTEqualStrategyNumber, F_OIDEQ,
3230  ObjectIdGetDatum(relid));
3231 
3232  if (attnum == 0)
3233  nkeys = 1;
3234  else
3235  {
3236  ScanKeyInit(&key[1],
3237  Anum_pg_statistic_staattnum,
3238  BTEqualStrategyNumber, F_INT2EQ,
3240  nkeys = 2;
3241  }
3242 
3243  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
3244  NULL, nkeys, key);
3245 
3246  /* we must loop even when attnum != 0, in case of inherited stats */
3247  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3248  CatalogTupleDelete(pgstatistic, &tuple->t_self);
3249 
3250  systable_endscan(scan);
3251 
3252  table_close(pgstatistic, RowExclusiveLock);
3253 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define Int16GetDatum(X)
Definition: postgres.h:495
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define StatisticRelidAttnumInhIndexId
Definition: pg_statistic.h:140
int16 attnum
Definition: pg_attribute.h:83
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
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 2150 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().

2151 {
2152  Datum valuesAtt[Natts_pg_attribute];
2153  bool nullsAtt[Natts_pg_attribute];
2154  bool replacesAtt[Natts_pg_attribute];
2155  Datum missingval;
2156  Form_pg_attribute attStruct;
2157  Relation attrrel,
2158  tablerel;
2159  HeapTuple atttup,
2160  newtup;
2161 
2162  /* lock the table the attribute belongs to */
2163  tablerel = table_open(relid, AccessExclusiveLock);
2164 
2165  /* Lock the attribute row and get the data */
2166  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2167  atttup = SearchSysCacheAttName(relid, attname);
2168  if (!HeapTupleIsValid(atttup))
2169  elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2170  attname, relid);
2171  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2172 
2173  /* get an array value from the value string */
2174  missingval = OidFunctionCall3(F_ARRAY_IN,
2176  ObjectIdGetDatum(attStruct->atttypid),
2177  Int32GetDatum(attStruct->atttypmod));
2178 
2179  /* update the tuple - set atthasmissing and attmissingval */
2180  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2181  MemSet(nullsAtt, false, sizeof(nullsAtt));
2182  MemSet(replacesAtt, false, sizeof(replacesAtt));
2183 
2184  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
2185  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2186  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2187  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2188 
2189  newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2190  valuesAtt, nullsAtt, replacesAtt);
2191  CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
2192 
2193  /* clean up */
2194  ReleaseSysCache(atttup);
2195  table_close(attrrel, RowExclusiveLock);
2196  table_close(tablerel, AccessExclusiveLock);
2197 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
static struct @142 value
#define RelationGetDescr(relation)
Definition: rel.h:495
#define MemSet(start, val, len)
Definition: c.h:1008
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
NameData attname
Definition: pg_attribute.h:41
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition: fmgr.h:668
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define BoolGetDatum(X)
Definition: postgres.h:446
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1268
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define Int32GetDatum(X)
Definition: postgres.h:523
#define elog(elevel,...)
Definition: elog.h:232
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 2976 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().

2977 {
2978  Relation relrel;
2979  HeapTuple reltup;
2980  Form_pg_class relStruct;
2981 
2982  relrel = table_open(RelationRelationId, RowExclusiveLock);
2983  reltup = SearchSysCacheCopy1(RELOID,
2985  if (!HeapTupleIsValid(reltup))
2986  elog(ERROR, "cache lookup failed for relation %u",
2987  RelationGetRelid(rel));
2988  relStruct = (Form_pg_class) GETSTRUCT(reltup);
2989 
2990  if (relStruct->relchecks != numchecks)
2991  {
2992  relStruct->relchecks = numchecks;
2993 
2994  CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
2995  }
2996  else
2997  {
2998  /* Skip the disk update, but force relcache inval anyway */
3000  }
3001 
3002  heap_freetuple(reltup);
3003  table_close(relrel, RowExclusiveLock);
3004 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
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:301
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
#define elog(elevel,...)
Definition: elog.h:232
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:469

◆ StoreAttrDefault()

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

Definition at line 2211 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(), ATExecCookedColumnDefault(), and StoreConstraints().

2213 {
2214  char *adbin;
2215  Relation adrel;
2216  HeapTuple tuple;
2217  Datum values[4];
2218  static bool nulls[4] = {false, false, false, false};
2219  Relation attrrel;
2220  HeapTuple atttup;
2221  Form_pg_attribute attStruct;
2222  char attgenerated;
2223  Oid attrdefOid;
2224  ObjectAddress colobject,
2225  defobject;
2226 
2227  adrel = table_open(AttrDefaultRelationId, RowExclusiveLock);
2228 
2229  /*
2230  * Flatten expression to string form for storage.
2231  */
2232  adbin = nodeToString(expr);
2233 
2234  /*
2235  * Make the pg_attrdef entry.
2236  */
2237  attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId,
2238  Anum_pg_attrdef_oid);
2239  values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid);
2240  values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
2241  values[Anum_pg_attrdef_adnum - 1] = attnum;
2242  values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
2243 
2244  tuple = heap_form_tuple(adrel->rd_att, values, nulls);
2245  CatalogTupleInsert(adrel, tuple);
2246 
2247  defobject.classId = AttrDefaultRelationId;
2248  defobject.objectId = attrdefOid;
2249  defobject.objectSubId = 0;
2250 
2251  table_close(adrel, RowExclusiveLock);
2252 
2253  /* now can free some of the stuff allocated above */
2254  pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
2255  heap_freetuple(tuple);
2256  pfree(adbin);
2257 
2258  /*
2259  * Update the pg_attribute entry for the column to show that a default
2260  * exists.
2261  */
2262  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2263  atttup = SearchSysCacheCopy2(ATTNUM,
2266  if (!HeapTupleIsValid(atttup))
2267  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2268  attnum, RelationGetRelid(rel));
2269  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2270  attgenerated = attStruct->attgenerated;
2271  if (!attStruct->atthasdef)
2272  {
2273  Form_pg_attribute defAttStruct;
2274 
2275  ExprState *exprState;
2276  Expr *expr2 = (Expr *) expr;
2277  EState *estate = NULL;
2278  ExprContext *econtext;
2279  Datum valuesAtt[Natts_pg_attribute];
2280  bool nullsAtt[Natts_pg_attribute];
2281  bool replacesAtt[Natts_pg_attribute];
2282  Datum missingval = (Datum) 0;
2283  bool missingIsNull = true;
2284 
2285  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2286  MemSet(nullsAtt, false, sizeof(nullsAtt));
2287  MemSet(replacesAtt, false, sizeof(replacesAtt));
2288  valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2289  replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2290 
2291  if (add_column_mode && !attgenerated)
2292  {
2293  expr2 = expression_planner(expr2);
2294  estate = CreateExecutorState();
2295  exprState = ExecPrepareExpr(expr2, estate);
2296  econtext = GetPerTupleExprContext(estate);
2297 
2298  missingval = ExecEvalExpr(exprState, econtext,
2299  &missingIsNull);
2300 
2301  FreeExecutorState(estate);
2302 
2303  defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1);
2304 
2305  if (missingIsNull)
2306  {
2307  /* if the default evaluates to NULL, just store a NULL array */
2308  missingval = (Datum) 0;
2309  }
2310  else
2311  {
2312  /* otherwise make a one-element array of the value */
2313  missingval = PointerGetDatum(construct_array(&missingval,
2314  1,
2315  defAttStruct->atttypid,
2316  defAttStruct->attlen,
2317  defAttStruct->attbyval,
2318  defAttStruct->attalign));
2319  }
2320 
2321  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
2322  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2323  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2324  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2325  nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull;
2326  }
2327  atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2328  valuesAtt, nullsAtt, replacesAtt);
2329 
2330  CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
2331 
2332  if (!missingIsNull)
2333  pfree(DatumGetPointer(missingval));
2334 
2335  }
2336  table_close(attrrel, RowExclusiveLock);
2337  heap_freetuple(atttup);
2338 
2339  /*
2340  * Make a dependency so that the pg_attrdef entry goes away if the column
2341  * (or whole table) is deleted.
2342  */
2343  colobject.classId = RelationRelationId;
2344  colobject.objectId = RelationGetRelid(rel);
2345  colobject.objectSubId = attnum;
2346 
2347  recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
2348 
2349  /*
2350  * Record dependencies on objects used in the expression, too.
2351  */
2352  if (attgenerated)
2353  {
2354  /*
2355  * Generated column: Dropping anything that the generation expression
2356  * refers to automatically drops the generated column.
2357  */
2358  recordDependencyOnSingleRelExpr(&colobject, expr, RelationGetRelid(rel),
2360  DEPENDENCY_AUTO, false);
2361  }
2362  else
2363  {
2364  /*
2365  * Normal default: Dropping anything that the default refers to
2366  * requires CASCADE and drops the default only.
2367  */
2368  recordDependencyOnSingleRelExpr(&defobject, expr, RelationGetRelid(rel),
2370  DEPENDENCY_NORMAL, false);
2371  }
2372 
2373  /*
2374  * Post creation hook for attribute defaults.
2375  *
2376  * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
2377  * couple of deletion/creation of the attribute's default entry, so the
2378  * callee should check existence of an older version of this entry if it
2379  * needs to distinguish.
2380  */
2381  InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
2382  RelationGetRelid(rel), attnum, is_internal);
2383 
2384  return attrdefOid;
2385 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:495
#define PointerGetDatum(X)
Definition: postgres.h:600
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Expr * expression_planner(Expr *expr)
Definition: planner.c:5653
#define Int16GetDatum(X)
Definition: postgres.h:495
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3318
#define MemSet(start, val, len)
Definition: c.h:1008
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:692
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
#define GetPerTupleExprContext(estate)
Definition: executor.h:532
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:315
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
EState * CreateExecutorState(void)
Definition: execUtils.c:90
uintptr_t Datum
Definition: postgres.h:411
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:153
TupleDesc rd_att
Definition: rel.h:110
int16 attnum
Definition: pg_attribute.h:83
#define AttrDefaultOidIndexId
Definition: pg_attrdef.h:55
#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:1621
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define DatumGetPointer(X)
Definition: postgres.h:593
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define elog(elevel,...)
Definition: elog.h:232
#define CStringGetTextDatum(s)
Definition: builtins.h:82
char * nodeToString(const void *obj)
Definition: outfuncs.c:4526
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:177
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:469
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ StoreConstraints()

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

Definition at line 2504 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().

2505 {
2506  int numchecks = 0;
2507  ListCell *lc;
2508 
2509  if (cooked_constraints == NIL)
2510  return; /* nothing to do */
2511 
2512  /*
2513  * Deparsing of constraint expressions will fail unless the just-created
2514  * pg_attribute tuples for this relation are made visible. So, bump the
2515  * command counter. CAUTION: this will cause a relcache entry rebuild.
2516  */
2518 
2519  foreach(lc, cooked_constraints)
2520  {
2521  CookedConstraint *con = (CookedConstraint *) lfirst(lc);
2522 
2523  switch (con->contype)
2524  {
2525  case CONSTR_DEFAULT:
2526  con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
2527  is_internal, false);
2528  break;
2529  case CONSTR_CHECK:
2530  con->conoid =
2531  StoreRelCheck(rel, con->name, con->expr,
2532  !con->skip_validation, con->is_local,
2533  con->inhcount, con->is_no_inherit,
2534  is_internal);
2535  numchecks++;
2536  break;
2537  default:
2538  elog(ERROR, "unrecognized constraint type: %d",
2539  (int) con->contype);
2540  }
2541  }
2542 
2543  if (numchecks > 0)
2544  SetRelationNumChecks(rel, numchecks);
2545 }
#define NIL
Definition: pg_list.h:65
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2976
bool is_no_inherit
Definition: heap.h:45
AttrNumber attnum
Definition: heap.h:40
#define ERROR
Definition: elog.h:46
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:2211
void CommandCounterIncrement(void)
Definition: xact.c:1021
#define lfirst(lc)
Definition: pg_list.h:169
#define elog(elevel,...)
Definition: elog.h:232
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:2396
bool is_local
Definition: heap.h:43

◆ StorePartitionBound()

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

Definition at line 3778 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().

3779 {
3780  Relation classRel;
3781  HeapTuple tuple,
3782  newtuple;
3783  Datum new_val[Natts_pg_class];
3784  bool new_null[Natts_pg_class],
3785  new_repl[Natts_pg_class];
3786  Oid defaultPartOid;
3787 
3788  /* Update pg_class tuple */
3789  classRel = table_open(RelationRelationId, RowExclusiveLock);
3790  tuple = SearchSysCacheCopy1(RELOID,
3792  if (!HeapTupleIsValid(tuple))
3793  elog(ERROR, "cache lookup failed for relation %u",
3794  RelationGetRelid(rel));
3795 
3796 #ifdef USE_ASSERT_CHECKING
3797  {
3798  Form_pg_class classForm;
3799  bool isnull;
3800 
3801  classForm = (Form_pg_class) GETSTRUCT(tuple);
3802  Assert(!classForm->relispartition);
3803  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3804  &isnull);
3805  Assert(isnull);
3806  }
3807 #endif
3808 
3809  /* Fill in relpartbound value */
3810  memset(new_val, 0, sizeof(new_val));
3811  memset(new_null, false, sizeof(new_null));
3812  memset(new_repl, false, sizeof(new_repl));
3813  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3814  new_null[Anum_pg_class_relpartbound - 1] = false;
3815  new_repl[Anum_pg_class_relpartbound - 1] = true;
3816  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3817  new_val, new_null, new_repl);
3818  /* Also set the flag */
3819  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3820  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3821  heap_freetuple(newtuple);
3822  table_close(classRel, RowExclusiveLock);
3823 
3824  /*
3825  * If we're storing bounds for the default partition, update
3826  * pg_partitioned_table too.
3827  */
3828  if (bound->is_default)
3830  RelationGetRelid(rel));
3831 
3832  /* Make these updates visible */
3834 
3835  /*
3836  * The partition constraint for the default partition depends on the
3837  * partition bounds of every other partition, so we must invalidate the
3838  * relcache entry for that partition every time a partition is added or
3839  * removed.
3840  */
3841  defaultPartOid =
3843  if (OidIsValid(defaultPartOid))
3844  CacheInvalidateRelcacheByRelid(defaultPartOid);
3845 
3846  CacheInvalidateRelcache(parent);
3847 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:495
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:338
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached)
Definition: partdesc.c:72
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1337
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
#define elog(elevel,...)
Definition: elog.h:232
#define CStringGetTextDatum(s)
Definition: builtins.h:82
char * nodeToString(const void *obj)
Definition: outfuncs.c:4526
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:469
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
Definition: partdesc.c:455

◆ StorePartitionKey()

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

Definition at line 3620 of file heap.c.

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

Referenced by DefineRelation().

3627 {
3628  int i;
3629  int2vector *partattrs_vec;
3630  oidvector *partopclass_vec;
3631  oidvector *partcollation_vec;
3632  Datum partexprDatum;
3633  Relation pg_partitioned_table;
3634  HeapTuple tuple;
3635  Datum values[Natts_pg_partitioned_table];
3636  bool nulls[Natts_pg_partitioned_table];
3637  ObjectAddress myself;
3638  ObjectAddress referenced;
3639  ObjectAddresses *addrs;
3640 
3641  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3642 
3643  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3644  partattrs_vec = buildint2vector(partattrs, partnatts);
3645  partopclass_vec = buildoidvector(partopclass, partnatts);
3646  partcollation_vec = buildoidvector(partcollation, partnatts);
3647 
3648  /* Convert the expressions (if any) to a text datum */
3649  if (partexprs)
3650  {
3651  char *exprString;
3652 
3653  exprString = nodeToString(partexprs);
3654  partexprDatum = CStringGetTextDatum(exprString);
3655  pfree(exprString);
3656  }
3657  else
3658  partexprDatum = (Datum) 0;
3659 
3660  pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
3661 
3662  MemSet(nulls, false, sizeof(nulls));
3663 
3664  /* Only this can ever be NULL */
3665  if (!partexprDatum)
3666  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3667 
3668  values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
3669  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3670  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3671  values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
3672  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3673  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3674  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3675  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3676 
3677  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3678 
3679  CatalogTupleInsert(pg_partitioned_table, tuple);
3680  table_close(pg_partitioned_table, RowExclusiveLock);
3681 
3682  /* Mark this relation as dependent on a few things as follows */
3683  addrs = new_object_addresses();
3684  ObjectAddressSet(myself, RelationRelationId, RelationGetRelid(rel));
3685 
3686  /* Operator class and collation per key column */
3687  for (i = 0; i < partnatts; i++)
3688  {
3689  ObjectAddressSet(referenced, OperatorClassRelationId, partopclass[i]);
3690  add_exact_object_address(&referenced, addrs);
3691 
3692  /* The default collation is pinned, so don't bother recording it */
3693  if (OidIsValid(partcollation[i]) &&
3694  partcollation[i] != DEFAULT_COLLATION_OID)
3695  {
3696  ObjectAddressSet(referenced, CollationRelationId, partcollation[i]);
3697  add_exact_object_address(&referenced, addrs);
3698  }
3699  }
3700 
3702  free_object_addresses(addrs);
3703 
3704  /*
3705  * The partitioning columns are made internally dependent on the table,
3706  * because we cannot drop any of them without dropping the whole table.
3707  * (ATExecDropColumn independently enforces that, but it's not bulletproof
3708  * so we need the dependencies too.)
3709  */
3710  for (i = 0; i < partnatts; i++)
3711  {
3712  if (partattrs[i] == 0)
3713  continue; /* ignore expressions here */
3714 
3715  ObjectAddressSubSet(referenced, RelationRelationId,
3716  RelationGetRelid(rel), partattrs[i]);
3717  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
3718  }
3719 
3720  /*
3721  * Also consider anything mentioned in partition expressions. External
3722  * references (e.g. functions) get NORMAL dependencies. Table columns
3723  * mentioned in the expressions are handled the same as plain partitioning
3724  * columns, i.e. they become internally dependent on the whole table.
3725  */
3726  if (partexprs)
3728  (Node *) partexprs,
3729  RelationGetRelid(rel),
3732  true /* reverse the self-deps */ );
3733 
3734  /*
3735  * We must invalidate the relcache so that the next
3736  * CommandCounterIncrement() will cause the same to be rebuilt using the
3737  * information in just created catalog entry.
3738  */
3740 }
Definition: c.h:660
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define RelationGetDescr(relation)
Definition: rel.h:495
#define PointerGetDatum(X)
Definition: postgres.h:600
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2701
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:114
#define Int16GetDatum(X)
Definition: postgres.h:495
Definition: nodes.h:539
#define MemSet(start, val, len)
Definition: c.h:1008
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2492
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2437
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2732
Form_pg_class rd_rel
Definition: rel.h:109
#define OidIsValid(objectId)
Definition: c.h:710
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define RowExclusiveLock
Definition: lockdefs.h:38
Definition: c.h:649
uintptr_t Datum
Definition: postgres.h:411
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:804
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:1621
#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
#define CharGetDatum(X)
Definition: postgres.h:460
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
static Datum values[MAXATTR]
Definition: bootstrap.c:166
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:82
char * nodeToString(const void *obj)
Definition: outfuncs.c:4526
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:469
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

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

2399 {
2400  char *ccbin;
2401  List *varList;
2402  int keycount;
2403  int16 *attNos;
2404  Oid constrOid;
2405 
2406  /*
2407  * Flatten expression to string form for storage.
2408  */
2409  ccbin = nodeToString(expr);
2410 
2411  /*
2412  * Find columns of rel that are used in expr
2413  *
2414  * NB: pull_var_clause is okay here only because we don't allow subselects
2415  * in check constraints; it would fail to examine the contents of
2416  * subselects.
2417  */
2418  varList = pull_var_clause(expr, 0);
2419  keycount = list_length(varList);
2420 
2421  if (keycount > 0)
2422  {
2423  ListCell *vl;
2424  int i = 0;
2425 
2426  attNos = (int16 *) palloc(keycount * sizeof(int16));
2427  foreach(vl, varList)
2428  {
2429  Var *var = (Var *) lfirst(vl);
2430  int j;
2431 
2432  for (j = 0; j < i; j++)
2433  if (attNos[j] == var->varattno)
2434  break;
2435  if (j == i)
2436  attNos[i++] = var->varattno;
2437  }
2438  keycount = i;
2439  }
2440  else
2441  attNos = NULL;
2442 
2443  /*
2444  * Partitioned tables do not contain any rows themselves, so a NO INHERIT
2445  * constraint makes no sense.
2446  */
2447  if (is_no_inherit &&
2448  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2449  ereport(ERROR,
2450  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2451  errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
2452  RelationGetRelationName(rel))));
2453 
2454  /*
2455  * Create the Check Constraint
2456  */
2457  constrOid =
2458  CreateConstraintEntry(ccname, /* Constraint Name */
2459  RelationGetNamespace(rel), /* namespace */
2460  CONSTRAINT_CHECK, /* Constraint Type */
2461  false, /* Is Deferrable */
2462  false, /* Is Deferred */
2463  is_validated,
2464  InvalidOid, /* no parent constraint */
2465  RelationGetRelid(rel), /* relation */
2466  attNos, /* attrs in the constraint */
2467  keycount, /* # key attrs in the constraint */
2468  keycount, /* # total attrs in the constraint */
2469  InvalidOid, /* not a domain constraint */
2470  InvalidOid, /* no associated index */
2471  InvalidOid, /* Foreign key fields */
2472  NULL,
2473  NULL,
2474  NULL,
2475  NULL,
2476  0,
2477  ' ',
2478  ' ',
2479  ' ',
2480  NULL, /* not an exclusion constraint */
2481  expr, /* Tree form of check constraint */
2482  ccbin, /* Binary form of check constraint */
2483  is_local, /* conislocal */
2484  inhcount, /* coninhcount */
2485  is_no_inherit, /* connoinherit */
2486  is_internal); /* internally constructed? */
2487 
2488  pfree(ccbin);
2489 
2490  return constrOid;
2491 }
signed short int16
Definition: c.h:428
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, 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:698
AttrNumber varattno
Definition: primnodes.h:191
List * pull_var_clause(Node *node, int flags)
Definition: var.c:562
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:186
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
#define RelationGetRelationName(relation)
Definition: rel.h:503
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
char * nodeToString(const void *obj)
Definition: outfuncs.c:4526
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:469
#define RelationGetNamespace(relation)
Definition: rel.h:510

◆ SystemAttributeByName()

const FormData_pg_attribute* SystemAttributeByName ( const char *  attname)

Definition at line 262 of file heap.c.

References FormData_pg_attribute, lengthof, NameStr, and SysAtt.

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

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

◆ SystemAttributeDefinition()

const FormData_pg_attribute* SystemAttributeDefinition ( AttrNumber  attno)

Definition at line 250 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().

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

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:120
bool attnotnull
Definition: pg_attribute.h:129
bool attbyval
Definition: pg_attribute.h:112
char attalign
Definition: pg_attribute.h:126