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

Go to the source code of this file.

Functions

static void AddNewRelationTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, Oid reloftype, Oid relowner, char relkind, TransactionId relfrozenxid, TransactionId relminmxid, Datum relacl, Datum reloptions)
 
static ObjectAddress AddNewRelationType (const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, Oid ownerid, Oid new_row_type, Oid new_array_type)
 
static void RelationRemoveInheritance (Oid relid)
 
static Oid StoreRelCheck (Relation rel, const char *ccname, Node *expr, bool is_validated, bool is_local, int inhcount, bool is_no_inherit, bool is_internal)
 
static void StoreConstraints (Relation rel, List *cooked_constraints, bool is_internal)
 
static bool MergeWithExistingConstraint (Relation rel, const char *ccname, Node *expr, bool allow_merge, bool is_local, bool is_initially_valid, bool is_no_inherit)
 
static void SetRelationNumChecks (Relation rel, int numchecks)
 
static NodecookConstraint (ParseState *pstate, Node *raw_constraint, char *relname)
 
const FormData_pg_attributeSystemAttributeDefinition (AttrNumber attno)
 
const FormData_pg_attributeSystemAttributeByName (const char *attname)
 
Relation heap_create (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid relfilenode, Oid accessmtd, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods, TransactionId *relfrozenxid, MultiXactId *relminmxid)
 
void CheckAttributeNamesTypes (TupleDesc tupdesc, char relkind, int flags)
 
void CheckAttributeType (const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
 
void 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 842 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().

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

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

Referenced by heap_create_with_catalog().

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

References DEFAULT_TYPDELIM, InvalidOid, and TypeCreate().

Referenced by heap_create_with_catalog().

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

◆ AddRelationNewConstraints()

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

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

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

◆ check_nested_generated()

static void check_nested_generated ( ParseState pstate,
Node node 
)
static

Definition at line 3029 of file heap.c.

References check_nested_generated_walker().

Referenced by cookDefault().

3030 {
3031  check_nested_generated_walker(node, pstate);
3032 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:2998

◆ check_nested_generated_walker()

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

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

2999 {
3000  ParseState *pstate = context;
3001 
3002  if (node == NULL)
3003  return false;
3004  else if (IsA(node, Var))
3005  {
3006  Var *var = (Var *) node;
3007  Oid relid;
3009 
3010  relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
3011  attnum = var->varattno;
3012 
3013  if (OidIsValid(relid) && AttributeNumberIsValid(attnum) && get_attgenerated(relid, attnum))
3014  ereport(ERROR,
3015  (errcode(ERRCODE_SYNTAX_ERROR),
3016  errmsg("cannot use generated column \"%s\" in column generation expression",
3017  get_attname(relid, attnum, false)),
3018  errdetail("A generated column cannot reference another generated column."),
3019  parser_errposition(pstate, var->location)));
3020 
3021  return false;
3022  }
3023  else
3025  (void *) context);
3026 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:2998
#define IsA(nodeptr, _type_)
Definition: nodes.h:581
int errcode(int sqlerrcode)
Definition: elog.c:704
AttrNumber varattno
Definition: primnodes.h:186
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:181
#define OidIsValid(objectId)
Definition: c.h:710
#define ERROR
Definition: elog.h:45
int location
Definition: primnodes.h:196
int errdetail(const char *fmt,...)
Definition: elog.c:1048
#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:184
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
int16 attnum
Definition: pg_attribute.h:83
#define ereport(elevel,...)
Definition: elog.h:155
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1885
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:915
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:181

◆ CheckAttributeNamesTypes()

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

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

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

◆ CheckAttributeType()

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

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

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

3125 {
3126  Node *expr;
3127 
3128  /*
3129  * Transform raw parsetree to executable expression.
3130  */
3131  expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
3132 
3133  /*
3134  * Make sure it yields a boolean result.
3135  */
3136  expr = coerce_to_boolean(pstate, expr, "CHECK");
3137 
3138  /*
3139  * Take care of collations.
3140  */
3141  assign_expr_collations(pstate, expr);
3142 
3143  /*
3144  * Make sure no outside relations are referred to (this is probably dead
3145  * code now that add_missing_from is history).
3146  */
3147  if (list_length(pstate->p_rtable) != 1)
3148  ereport(ERROR,
3149  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
3150  errmsg("only table \"%s\" can be referenced in check constraint",
3151  relname)));
3152 
3153  return expr;
3154 }
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:94
Definition: nodes.h:530
int errcode(int sqlerrcode)
Definition: elog.c:704
NameData relname
Definition: pg_class.h:38
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ERROR
Definition: elog.h:45
#define ereport(elevel,...)
Definition: elog.h:155
static int list_length(const List *l)
Definition: pg_list.h:149
int errmsg(const char *fmt,...)
Definition: elog.c:915
List * p_rtable
Definition: parse_node.h:181
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 3047 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().

3053 {
3054  Node *expr;
3055 
3056  Assert(raw_default != NULL);
3057 
3058  /*
3059  * Transform raw parsetree to executable expression.
3060  */
3061  expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
3062 
3063  if (attgenerated)
3064  {
3065  check_nested_generated(pstate, expr);
3066 
3067  if (contain_mutable_functions(expr))
3068  ereport(ERROR,
3069  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3070  errmsg("generation expression is not immutable")));
3071  }
3072  else
3073  {
3074  /*
3075  * For a default expression, transformExpr() should have rejected
3076  * column references.
3077  */
3078  Assert(!contain_var_clause(expr));
3079  }
3080 
3081  /*
3082  * Coerce the expression to the correct type and typmod, if given. This
3083  * should match the parser's processing of non-defaulted expressions ---
3084  * see transformAssignedExpr().
3085  */
3086  if (OidIsValid(atttypid))
3087  {
3088  Oid type_id = exprType(expr);
3089 
3090  expr = coerce_to_target_type(pstate, expr, type_id,
3091  atttypid, atttypmod,
3094  -1);
3095  if (expr == NULL)
3096  ereport(ERROR,
3097  (errcode(ERRCODE_DATATYPE_MISMATCH),
3098  errmsg("column \"%s\" is of type %s"
3099  " but default expression is of type %s",
3100  attname,
3101  format_type_be(atttypid),
3102  format_type_be(type_id)),
3103  errhint("You will need to rewrite or cast the expression.")));
3104  }
3105 
3106  /*
3107  * Finally, take care of collations in the finished expression.
3108  */
3109  assign_expr_collations(pstate, expr);
3110 
3111  return expr;
3112 }
int errhint(const char *fmt,...)
Definition: elog.c:1162
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:94
Definition: nodes.h:530
int errcode(int sqlerrcode)
Definition: elog.c:704
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:45
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:155
#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:3029
int errmsg(const char *fmt,...)
Definition: elog.c:915
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:358

◆ CopyStatistics()

void CopyStatistics ( Oid  fromrelid,
Oid  torelid 
)

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

3161 {
3162  HeapTuple tup;
3163  SysScanDesc scan;
3164  ScanKeyData key[1];
3165  Relation statrel;
3166 
3167  statrel = table_open(StatisticRelationId, RowExclusiveLock);
3168 
3169  /* Now search for stat records */
3170  ScanKeyInit(&key[0],
3171  Anum_pg_statistic_starelid,
3172  BTEqualStrategyNumber, F_OIDEQ,
3173  ObjectIdGetDatum(fromrelid));
3174 
3176  true, NULL, 1, key);
3177 
3178  while (HeapTupleIsValid((tup = systable_getnext(scan))))
3179  {
3180  Form_pg_statistic statform;
3181 
3182  /* make a modifiable copy */
3183  tup = heap_copytuple(tup);
3184  statform = (Form_pg_statistic) GETSTRUCT(tup);
3185 
3186  /* update the copy of the tuple and insert it */
3187  statform->starelid = torelid;
3188  CatalogTupleInsert(statrel, tup);
3189 
3190  heap_freetuple(tup);
3191  }
3192 
3193  systable_endscan(scan);
3194 
3195  table_close(statrel, RowExclusiveLock);
3196 }
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:655
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:507
#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:222
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ DeleteAttributeTuples()

void DeleteAttributeTuples ( Oid  relid)

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

1582 {
1583  Relation attrel;
1584  SysScanDesc scan;
1585  ScanKeyData key[1];
1586  HeapTuple atttup;
1587 
1588  /* Grab an appropriate lock on the pg_attribute relation */
1589  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1590 
1591  /* Use the index to scan only attributes of the target relation */
1592  ScanKeyInit(&key[0],
1593  Anum_pg_attribute_attrelid,
1594  BTEqualStrategyNumber, F_OIDEQ,
1595  ObjectIdGetDatum(relid));
1596 
1597  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1598  NULL, 1, key);
1599 
1600  /* Delete all the matching tuples */
1601  while ((atttup = systable_getnext(scan)) != NULL)
1602  CatalogTupleDelete(attrel, &atttup->t_self);
1603 
1604  /* Clean up after the scan */
1605  systable_endscan(scan);
1606  table_close(attrel, RowExclusiveLock);
1607 }
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:351
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:507
ItemPointerData t_self
Definition: htup.h:65
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:202
#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 1552 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().

1553 {
1554  Relation pg_class_desc;
1555  HeapTuple tup;
1556 
1557  /* Grab an appropriate lock on the pg_class relation */
1558  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1559 
1560  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1561  if (!HeapTupleIsValid(tup))
1562  elog(ERROR, "cache lookup failed for relation %u", relid);
1563 
1564  /* delete the relation tuple from pg_class, and finish up */
1565  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1566 
1567  ReleaseSysCache(tup);
1568 
1569  table_close(pg_class_desc, RowExclusiveLock);
1570 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:351
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
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:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

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

1619 {
1620  Relation attrel;
1621  SysScanDesc scan;
1622  ScanKeyData key[2];
1623  HeapTuple atttup;
1624 
1625  /* Grab an appropriate lock on the pg_attribute relation */
1626  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1627 
1628  /* Use the index to scan only system attributes of the target relation */
1629  ScanKeyInit(&key[0],
1630  Anum_pg_attribute_attrelid,
1631  BTEqualStrategyNumber, F_OIDEQ,
1632  ObjectIdGetDatum(relid));
1633  ScanKeyInit(&key[1],
1634  Anum_pg_attribute_attnum,
1635  BTLessEqualStrategyNumber, F_INT2LE,
1636  Int16GetDatum(0));
1637 
1638  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1639  NULL, 2, key);
1640 
1641  /* Delete all the matching tuples */
1642  while ((atttup = systable_getnext(scan)) != NULL)
1643  CatalogTupleDelete(attrel, &atttup->t_self);
1644 
1645  /* Clean up after the scan */
1646  systable_endscan(scan);
1647  table_close(attrel, RowExclusiveLock);
1648 }
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:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:351
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:507
ItemPointerData t_self
Definition: htup.h:65
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:202
#define RowExclusiveLock
Definition: lockdefs.h:38
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ heap_create()

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

Definition at line 294 of file heap.c.

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

Referenced by heap_create_with_catalog(), and index_create().

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

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

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

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

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

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

◆ heap_truncate()

void heap_truncate ( List relids)

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

3301 {
3302  List *relations = NIL;
3303  ListCell *cell;
3304 
3305  /* Open relations for processing, and grab exclusive access on each */
3306  foreach(cell, relids)
3307  {
3308  Oid rid = lfirst_oid(cell);
3309  Relation rel;
3310 
3311  rel = table_open(rid, AccessExclusiveLock);
3312  relations = lappend(relations, rel);
3313  }
3314 
3315  /* Don't allow truncate on tables that are referenced by foreign keys */
3316  heap_truncate_check_FKs(relations, true);
3317 
3318  /* OK to do it */
3319  foreach(cell, relations)
3320  {
3321  Relation rel = lfirst(cell);
3322 
3323  /* Truncate the relation */
3324  heap_truncate_one_rel(rel);
3325 
3326  /* Close the relation, but keep exclusive lock on it until commit */
3327  table_close(rel, NoLock);
3328  }
3329 }
#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:3341
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3385
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 3385 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().

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

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

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

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

3342 {
3343  Oid toastrelid;
3344 
3345  /*
3346  * Truncate the relation. Partitioned tables have no storage, so there is
3347  * nothing to do for them here.
3348  */
3349  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3350  return;
3351 
3352  /* Truncate the underlying relation */
3354 
3355  /* If the relation has indexes, truncate the indexes too */
3357 
3358  /* If there is a toast table, truncate that too */
3359  toastrelid = rel->rd_rel->reltoastrelid;
3360  if (OidIsValid(toastrelid))
3361  {
3362  Relation toastrel = table_open(toastrelid, AccessExclusiveLock);
3363 
3365  RelationTruncateIndexes(toastrel);
3366  /* keep the lock... */
3367  table_close(toastrel, NoLock);
3368  }
3369 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Form_pg_class rd_rel
Definition: rel.h:110
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:1520
#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:3252

◆ InsertPgAttributeTuples()

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

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

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

◆ InsertPgClassTuple()

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

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

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

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

2818 {
2819  bool found;
2820  Relation conDesc;
2821  SysScanDesc conscan;
2822  ScanKeyData skey[3];
2823  HeapTuple tup;
2824 
2825  /* Search for a pg_constraint entry with same name and relation */
2826  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
2827 
2828  found = false;
2829 
2830  ScanKeyInit(&skey[0],
2831  Anum_pg_constraint_conrelid,
2832  BTEqualStrategyNumber, F_OIDEQ,
2834  ScanKeyInit(&skey[1],
2835  Anum_pg_constraint_contypid,
2836  BTEqualStrategyNumber, F_OIDEQ,
2838  ScanKeyInit(&skey[2],
2839  Anum_pg_constraint_conname,
2840  BTEqualStrategyNumber, F_NAMEEQ,
2841  CStringGetDatum(ccname));
2842 
2843  conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId, true,
2844  NULL, 3, skey);
2845 
2846  /* There can be at most one matching row */
2847  if (HeapTupleIsValid(tup = systable_getnext(conscan)))
2848  {
2850 
2851  /* Found it. Conflicts if not identical check constraint */
2852  if (con->contype == CONSTRAINT_CHECK)
2853  {
2854  Datum val;
2855  bool isnull;
2856 
2857  val = fastgetattr(tup,
2858  Anum_pg_constraint_conbin,
2859  conDesc->rd_att, &isnull);
2860  if (isnull)
2861  elog(ERROR, "null conbin for rel %s",
2863  if (equal(expr, stringToNode(TextDatumGetCString(val))))
2864  found = true;
2865  }
2866 
2867  /*
2868  * If the existing constraint is purely inherited (no local
2869  * definition) then interpret addition of a local constraint as a
2870  * legal merge. This allows ALTER ADD CONSTRAINT on parent and child
2871  * tables to be given in either order with same end state. However if
2872  * the relation is a partition, all inherited constraints are always
2873  * non-local, including those that were merged.
2874  */
2875  if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
2876  allow_merge = true;
2877 
2878  if (!found || !allow_merge)
2879  ereport(ERROR,
2881  errmsg("constraint \"%s\" for relation \"%s\" already exists",
2882  ccname, RelationGetRelationName(rel))));
2883 
2884  /* If the child constraint is "no inherit" then cannot merge */
2885  if (con->connoinherit)
2886  ereport(ERROR,
2887  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2888  errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
2889  ccname, RelationGetRelationName(rel))));
2890 
2891  /*
2892  * Must not change an existing inherited constraint to "no inherit"
2893  * status. That's because inherited constraints should be able to
2894  * propagate to lower-level children.
2895  */
2896  if (con->coninhcount > 0 && is_no_inherit)
2897  ereport(ERROR,
2898  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2899  errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
2900  ccname, RelationGetRelationName(rel))));
2901 
2902  /*
2903  * If the child constraint is "not valid" then cannot merge with a
2904  * valid parent constraint.
2905  */
2906  if (is_initially_valid && !con->convalidated)
2907  ereport(ERROR,
2908  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2909  errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
2910  ccname, RelationGetRelationName(rel))));
2911 
2912  /* OK to update the tuple */
2913  ereport(NOTICE,
2914  (errmsg("merging constraint \"%s\" with inherited definition",
2915  ccname)));
2916 
2917  tup = heap_copytuple(tup);
2918  con = (Form_pg_constraint) GETSTRUCT(tup);
2919 
2920  /*
2921  * In case of partitions, an inherited constraint must be inherited
2922  * only once since it cannot have multiple parents and it is never
2923  * considered local.
2924  */
2925  if (rel->rd_rel->relispartition)
2926  {
2927  con->coninhcount = 1;
2928  con->conislocal = false;
2929  }
2930  else
2931  {
2932  if (is_local)
2933  con->conislocal = true;
2934  else
2935  con->coninhcount++;
2936  }
2937 
2938  if (is_no_inherit)
2939  {
2940  Assert(is_local);
2941  con->connoinherit = true;
2942  }
2943 
2944  CatalogTupleUpdate(conDesc, &tup->t_self, tup);
2945  }
2946 
2947  systable_endscan(conscan);
2948  table_close(conDesc, RowExclusiveLock);
2949 
2950  return found;
2951 }
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:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3073
int errcode(int sqlerrcode)
Definition: elog.c:704
void * stringToNode(const char *str)
Definition: read.c:89
Form_pg_class rd_rel
Definition: rel.h:110
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:507
#define ERROR
Definition: elog.h:45
ItemPointerData t_self
Definition: htup.h:65
#define ConstraintRelidTypidNameIndexId
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:111
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:155
#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:302
int errmsg(const char *fmt,...)
Definition: elog.c:915
#define elog(elevel,...)
Definition: elog.h:228
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
#define RelationGetRelid(relation)
Definition: rel.h:457
long val
Definition: informix.c:664
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RelationClearMissing()

void RelationClearMissing ( Relation  rel)

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

2073 {
2074  Relation attr_rel;
2075  Oid relid = RelationGetRelid(rel);
2076  int natts = RelationGetNumberOfAttributes(rel);
2077  int attnum;
2078  Datum repl_val[Natts_pg_attribute];
2079  bool repl_null[Natts_pg_attribute];
2080  bool repl_repl[Natts_pg_attribute];
2081  Form_pg_attribute attrtuple;
2082  HeapTuple tuple,
2083  newtuple;
2084 
2085  memset(repl_val, 0, sizeof(repl_val));
2086  memset(repl_null, false, sizeof(repl_null));
2087  memset(repl_repl, false, sizeof(repl_repl));
2088 
2089  repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
2090  repl_null[Anum_pg_attribute_attmissingval - 1] = true;
2091 
2092  repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
2093  repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
2094 
2095 
2096  /* Get a lock on pg_attribute */
2097  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
2098 
2099  /* process each non-system attribute, including any dropped columns */
2100  for (attnum = 1; attnum <= natts; attnum++)
2101  {
2102  tuple = SearchSysCache2(ATTNUM,
2103  ObjectIdGetDatum(relid),
2104  Int16GetDatum(attnum));
2105  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
2106  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2107  attnum, relid);
2108 
2109  attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
2110 
2111  /* ignore any where atthasmissing is not true */
2112  if (attrtuple->atthasmissing)
2113  {
2114  newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
2115  repl_val, repl_null, repl_repl);
2116 
2117  CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
2118 
2119  heap_freetuple(newtuple);
2120  }
2121 
2122  ReleaseSysCache(tuple);
2123  }
2124 
2125  /*
2126  * Our update of the pg_attribute rows will force a relcache rebuild, so
2127  * there's nothing else to do here.
2128  */
2129  table_close(attr_rel, RowExclusiveLock);
2130 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:483
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:463
#define Int16GetDatum(X)
Definition: postgres.h:451
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define BoolGetDatum(X)
Definition: postgres.h:402
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:302
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
#define elog(elevel,...)
Definition: elog.h:228
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:457

◆ RelationRemoveInheritance()

static void RelationRemoveInheritance ( Oid  relid)
static

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

1520 {
1521  Relation catalogRelation;
1522  SysScanDesc scan;
1523  ScanKeyData key;
1524  HeapTuple tuple;
1525 
1526  catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
1527 
1528  ScanKeyInit(&key,
1529  Anum_pg_inherits_inhrelid,
1530  BTEqualStrategyNumber, F_OIDEQ,
1531  ObjectIdGetDatum(relid));
1532 
1533  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
1534  NULL, 1, &key);
1535 
1536  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1537  CatalogTupleDelete(catalogRelation, &tuple->t_self);
1538 
1539  systable_endscan(scan);
1540  table_close(catalogRelation, RowExclusiveLock);
1541 }
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:47
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:351
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:507
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 3252 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().

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

1774 {
1775  Relation attrdef_rel;
1776  ScanKeyData scankeys[2];
1777  SysScanDesc scan;
1778  HeapTuple tuple;
1779  bool found = false;
1780 
1781  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1782 
1783  ScanKeyInit(&scankeys[0],
1784  Anum_pg_attrdef_adrelid,
1785  BTEqualStrategyNumber, F_OIDEQ,
1786  ObjectIdGetDatum(relid));
1787  ScanKeyInit(&scankeys[1],
1788  Anum_pg_attrdef_adnum,
1789  BTEqualStrategyNumber, F_INT2EQ,
1791 
1792  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1793  NULL, 2, scankeys);
1794 
1795  /* There should be at most one matching tuple, but we loop anyway */
1796  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1797  {
1798  ObjectAddress object;
1799  Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
1800 
1801  object.classId = AttrDefaultRelationId;
1802  object.objectId = attrtuple->oid;
1803  object.objectSubId = 0;
1804 
1805  performDeletion(&object, behavior,
1806  internal ? PERFORM_DELETION_INTERNAL : 0);
1807 
1808  found = true;
1809  }
1810 
1811  systable_endscan(scan);
1812  table_close(attrdef_rel, RowExclusiveLock);
1813 
1814  if (complain && !found)
1815  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1816  relid, attnum);
1817 }
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:655
#define AttrDefaultIndexId
Definition: pg_attrdef.h:53
#define Int16GetDatum(X)
Definition: postgres.h:451
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
#define RowExclusiveLock
Definition: lockdefs.h:38
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:313
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:228
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:141

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

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

1828 {
1829  Relation attrdef_rel;
1830  Relation attr_rel;
1831  Relation myrel;
1832  ScanKeyData scankeys[1];
1833  SysScanDesc scan;
1834  HeapTuple tuple;
1835  Oid myrelid;
1836  AttrNumber myattnum;
1837 
1838  /* Grab an appropriate lock on the pg_attrdef relation */
1839  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1840 
1841  /* Find the pg_attrdef tuple */
1842  ScanKeyInit(&scankeys[0],
1843  Anum_pg_attrdef_oid,
1844  BTEqualStrategyNumber, F_OIDEQ,
1845  ObjectIdGetDatum(attrdefId));
1846 
1847  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1848  NULL, 1, scankeys);
1849 
1850  tuple = systable_getnext(scan);
1851  if (!HeapTupleIsValid(tuple))
1852  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1853 
1854  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1855  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1856 
1857  /* Get an exclusive lock on the relation owning the attribute */
1858  myrel = relation_open(myrelid, AccessExclusiveLock);
1859 
1860  /* Now we can delete the pg_attrdef row */
1861  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1862 
1863  systable_endscan(scan);
1864  table_close(attrdef_rel, RowExclusiveLock);
1865 
1866  /* Fix the pg_attribute row */
1867  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1868 
1869  tuple = SearchSysCacheCopy2(ATTNUM,
1870  ObjectIdGetDatum(myrelid),
1871  Int16GetDatum(myattnum));
1872  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1873  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1874  myattnum, myrelid);
1875 
1876  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1877 
1878  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1879 
1880  /*
1881  * Our update of the pg_attribute row will force a relcache rebuild, so
1882  * there's nothing else to do here.
1883  */
1884  table_close(attr_rel, RowExclusiveLock);
1885 
1886  /* Keep lock on attribute's rel until end of xact */
1887  relation_close(myrel, NoLock);
1888 }
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:655
#define Int16GetDatum(X)
Definition: postgres.h:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:351
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:507
#define ERROR
Definition: elog.h:45
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:197
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:302
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define elog(elevel,...)
Definition: elog.h:228
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 1659 of file heap.c.

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

Referenced by doDeletion().

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

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

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

3737 {
3738  Relation rel;
3739  HeapTuple tuple;
3740 
3741  rel = table_open(PartitionedRelationId, RowExclusiveLock);
3742 
3743  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3744  if (!HeapTupleIsValid(tuple))
3745  elog(ERROR, "cache lookup failed for partition key of relation %u",
3746  relid);
3747 
3748  CatalogTupleDelete(rel, &tuple->t_self);
3749 
3750  ReleaseSysCache(tuple);
3752 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:351
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
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:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

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

3206 {
3207  Relation pgstatistic;
3208  SysScanDesc scan;
3209  ScanKeyData key[2];
3210  int nkeys;
3211  HeapTuple tuple;
3212 
3213  pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
3214 
3215  ScanKeyInit(&key[0],
3216  Anum_pg_statistic_starelid,
3217  BTEqualStrategyNumber, F_OIDEQ,
3218  ObjectIdGetDatum(relid));
3219 
3220  if (attnum == 0)
3221  nkeys = 1;
3222  else
3223  {
3224  ScanKeyInit(&key[1],
3225  Anum_pg_statistic_staattnum,
3226  BTEqualStrategyNumber, F_INT2EQ,
3228  nkeys = 2;
3229  }
3230 
3231  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
3232  NULL, nkeys, key);
3233 
3234  /* we must loop even when attnum != 0, in case of inherited stats */
3235  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3236  CatalogTupleDelete(pgstatistic, &tuple->t_self);
3237 
3238  systable_endscan(scan);
3239 
3240  table_close(pgstatistic, RowExclusiveLock);
3241 }
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:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:351
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:507
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 2140 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().

2141 {
2142  Datum valuesAtt[Natts_pg_attribute];
2143  bool nullsAtt[Natts_pg_attribute];
2144  bool replacesAtt[Natts_pg_attribute];
2145  Datum missingval;
2146  Form_pg_attribute attStruct;
2147  Relation attrrel,
2148  tablerel;
2149  HeapTuple atttup,
2150  newtup;
2151 
2152  /* lock the table the attribute belongs to */
2153  tablerel = table_open(relid, AccessExclusiveLock);
2154 
2155  /* Lock the attribute row and get the data */
2156  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2157  atttup = SearchSysCacheAttName(relid, attname);
2158  if (!HeapTupleIsValid(atttup))
2159  elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2160  attname, relid);
2161  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2162 
2163  /* get an array value from the value string */
2164  missingval = OidFunctionCall3(F_ARRAY_IN,
2166  ObjectIdGetDatum(attStruct->atttypid),
2167  Int32GetDatum(attStruct->atttypmod));
2168 
2169  /* update the tuple - set atthasmissing and attmissingval */
2170  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2171  MemSet(nullsAtt, false, sizeof(nullsAtt));
2172  MemSet(replacesAtt, false, sizeof(replacesAtt));
2173 
2174  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
2175  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2176  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2177  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2178 
2179  newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2180  valuesAtt, nullsAtt, replacesAtt);
2181  CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
2182 
2183  /* clean up */
2184  ReleaseSysCache(atttup);
2185  table_close(attrrel, RowExclusiveLock);
2186  table_close(tablerel, AccessExclusiveLock);
2187 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:483
#define MemSet(start, val, len)
Definition: c.h:1008
static struct @141 value
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
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:578
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition: fmgr.h:668
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define BoolGetDatum(X)
Definition: postgres.h:402
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:302
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1268
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define Int32GetDatum(X)
Definition: postgres.h:479
#define elog(elevel,...)
Definition: elog.h:228
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 2964 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().

2965 {
2966  Relation relrel;
2967  HeapTuple reltup;
2968  Form_pg_class relStruct;
2969 
2970  relrel = table_open(RelationRelationId, RowExclusiveLock);
2971  reltup = SearchSysCacheCopy1(RELOID,
2973  if (!HeapTupleIsValid(reltup))
2974  elog(ERROR, "cache lookup failed for relation %u",
2975  RelationGetRelid(rel));
2976  relStruct = (Form_pg_class) GETSTRUCT(reltup);
2977 
2978  if (relStruct->relchecks != numchecks)
2979  {
2980  relStruct->relchecks = numchecks;
2981 
2982  CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
2983  }
2984  else
2985  {
2986  /* Skip the disk update, but force relcache inval anyway */
2988  }
2989 
2990  heap_freetuple(reltup);
2991  table_close(relrel, RowExclusiveLock);
2992 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
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:302
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:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:457

◆ StoreAttrDefault()

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

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

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

◆ StoreConstraints()

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

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

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

◆ StorePartitionBound()

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

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

3768 {
3769  Relation classRel;
3770  HeapTuple tuple,
3771  newtuple;
3772  Datum new_val[Natts_pg_class];
3773  bool new_null[Natts_pg_class],
3774  new_repl[Natts_pg_class];
3775  Oid defaultPartOid;
3776 
3777  /* Update pg_class tuple */
3778  classRel = table_open(RelationRelationId, RowExclusiveLock);
3779  tuple = SearchSysCacheCopy1(RELOID,
3781  if (!HeapTupleIsValid(tuple))
3782  elog(ERROR, "cache lookup failed for relation %u",
3783  RelationGetRelid(rel));
3784 
3785 #ifdef USE_ASSERT_CHECKING
3786  {
3787  Form_pg_class classForm;
3788  bool isnull;
3789 
3790  classForm = (Form_pg_class) GETSTRUCT(tuple);
3791  Assert(!classForm->relispartition);
3792  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3793  &isnull);
3794  Assert(isnull);
3795  }
3796 #endif
3797 
3798  /* Fill in relpartbound value */
3799  memset(new_val, 0, sizeof(new_val));
3800  memset(new_null, false, sizeof(new_null));
3801  memset(new_repl, false, sizeof(new_repl));
3802  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3803  new_null[Anum_pg_class_relpartbound - 1] = false;
3804  new_repl[Anum_pg_class_relpartbound - 1] = true;
3805  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3806  new_val, new_null, new_repl);
3807  /* Also set the flag */
3808  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3809  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3810  heap_freetuple(newtuple);
3811  table_close(classRel, RowExclusiveLock);
3812 
3813  /*
3814  * If we're storing bounds for the default partition, update
3815  * pg_partitioned_table too.
3816  */
3817  if (bound->is_default)
3819  RelationGetRelid(rel));
3820 
3821  /* Make these updates visible */
3823 
3824  /*
3825  * The partition constraint for the default partition depends on the
3826  * partition bounds of every other partition, so we must invalidate the
3827  * relcache entry for that partition every time a partition is added or
3828  * removed.
3829  */
3830  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3831  if (OidIsValid(defaultPartOid))
3832  CacheInvalidateRelcacheByRelid(defaultPartOid);
3833 
3834  CacheInvalidateRelcache(parent);
3835 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:483
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:316
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:507
#define ERROR
Definition: elog.h:45
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
PartitionDesc RelationGetPartitionDesc(Relation rel)
Definition: partdesc.c:64
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1337
uintptr_t Datum
Definition: postgres.h:367
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:302
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:228
#define CStringGetTextDatum(s)
Definition: builtins.h:82
char * nodeToString(const void *obj)
Definition: outfuncs.c:4424
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:457
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
Definition: partdesc.c:360

◆ StorePartitionKey()

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

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

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

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

2389 {
2390  char *ccbin;
2391  List *varList;
2392  int keycount;
2393  int16 *attNos;
2394  Oid constrOid;
2395 
2396  /*
2397  * Flatten expression to string form for storage.
2398  */
2399  ccbin = nodeToString(expr);
2400 
2401  /*
2402  * Find columns of rel that are used in expr
2403  *
2404  * NB: pull_var_clause is okay here only because we don't allow subselects
2405  * in check constraints; it would fail to examine the contents of
2406  * subselects.
2407  */
2408  varList = pull_var_clause(expr, 0);
2409  keycount = list_length(varList);
2410 
2411  if (keycount > 0)
2412  {
2413  ListCell *vl;
2414  int i = 0;
2415 
2416  attNos = (int16 *) palloc(keycount * sizeof(int16));
2417  foreach(vl, varList)
2418  {
2419  Var *var = (Var *) lfirst(vl);
2420  int j;
2421 
2422  for (j = 0; j < i; j++)
2423  if (attNos[j] == var->varattno)
2424  break;
2425  if (j == i)
2426  attNos[i++] = var->varattno;
2427  }
2428  keycount = i;
2429  }
2430  else
2431  attNos = NULL;
2432 
2433  /*
2434  * Partitioned tables do not contain any rows themselves, so a NO INHERIT
2435  * constraint makes no sense.
2436  */
2437  if (is_no_inherit &&
2438  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2439  ereport(ERROR,
2440  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2441  errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
2442  RelationGetRelationName(rel))));
2443 
2444  /*
2445  * Create the Check Constraint
2446  */
2447  constrOid =
2448  CreateConstraintEntry(ccname, /* Constraint Name */
2449  RelationGetNamespace(rel), /* namespace */
2450  CONSTRAINT_CHECK, /* Constraint Type */
2451  false, /* Is Deferrable */
2452  false, /* Is Deferred */
2453  is_validated,
2454  InvalidOid, /* no parent constraint */
2455  RelationGetRelid(rel), /* relation */
2456  attNos, /* attrs in the constraint */
2457  keycount, /* # key attrs in the constraint */
2458  keycount, /* # total attrs in the constraint */
2459  InvalidOid, /* not a domain constraint */
2460  InvalidOid, /* no associated index */
2461  InvalidOid, /* Foreign key fields */
2462  NULL,
2463  NULL,
2464  NULL,
2465  NULL,
2466  0,
2467  ' ',
2468  ' ',
2469  ' ',
2470  NULL, /* not an exclusion constraint */
2471  expr, /* Tree form of check constraint */
2472  ccbin, /* Binary form of check constraint */
2473  is_local, /* conislocal */
2474  inhcount, /* coninhcount */
2475  is_no_inherit, /* connoinherit */
2476  is_internal); /* internally constructed? */
2477 
2478  pfree(ccbin);
2479 
2480  return constrOid;
2481 }
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:704
AttrNumber varattno
Definition: primnodes.h:186
List * pull_var_clause(Node *node, int flags)
Definition: var.c:562
Form_pg_class rd_rel
Definition: rel.h:110
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:181
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:45
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:155
#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:950
int errmsg(const char *fmt,...)
Definition: elog.c:915
int i
char * nodeToString(const void *obj)
Definition: outfuncs.c:4424
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:457
#define RelationGetNamespace(relation)
Definition: rel.h:498

◆ SystemAttributeByName()

const FormData_pg_attribute* SystemAttributeByName ( const char *  attname)

Definition at line 261 of file heap.c.

References FormData_pg_attribute, lengthof, NameStr, and SysAtt.

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

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

◆ SystemAttributeDefinition()

const FormData_pg_attribute* SystemAttributeDefinition ( AttrNumber  attno)

Definition at line 249 of file heap.c.

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

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

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

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
int16 attnum
Definition: pg_attribute.h:83
struct ItemPointerData ItemPointerData
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21

Definition at line 151 of file heap.c.

Referenced by aclitem_eq(), aclitemComparator(), check_in_colors_match(), check_out_colors_match(), cmpaffix(), deccall2(), deccall3(), evalLazyFunc(), inet_merge(), inet_same_family(), int4gcd_internal(), int8gcd_internal(), macaddr8_cmp(), macaddr8_eq(),