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

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

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

Referenced by heap_create_with_catalog().

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

References DEFAULT_TYPDELIM, InvalidOid, and TypeCreate().

Referenced by heap_create_with_catalog().

1062 {
1063  return
1064  TypeCreate(new_row_type, /* optional predetermined OID */
1065  typeName, /* type name */
1066  typeNamespace, /* type namespace */
1067  new_rel_oid, /* relation oid */
1068  new_rel_kind, /* relation kind */
1069  ownerid, /* owner's ID */
1070  -1, /* internal size (varlena) */
1071  TYPTYPE_COMPOSITE, /* type-type (composite) */
1072  TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
1073  false, /* composite types are never preferred */
1074  DEFAULT_TYPDELIM, /* default array delimiter */
1075  F_RECORD_IN, /* input procedure */
1076  F_RECORD_OUT, /* output procedure */
1077  F_RECORD_RECV, /* receive procedure */
1078  F_RECORD_SEND, /* send procedure */
1079  InvalidOid, /* typmodin procedure - none */
1080  InvalidOid, /* typmodout procedure - none */
1081  InvalidOid, /* analyze procedure - default */
1082  InvalidOid, /* array element type - irrelevant */
1083  false, /* this is not an array type */
1084  new_array_type, /* array type if any */
1085  InvalidOid, /* domain base type - irrelevant */
1086  NULL, /* default value - none */
1087  NULL, /* default binary representation */
1088  false, /* passed by reference */
1089  TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1090  TYPSTORAGE_EXTENDED, /* fully TOASTable */
1091  -1, /* typmod */
1092  0, /* array dimensions for typBaseType */
1093  false, /* Type NOT NULL */
1094  InvalidOid); /* rowtypes never have a collation */
1095 }
#define InvalidOid
Definition: postgres_ext.h:36
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
ObjectAddress TypeCreate(Oid newTypeOid, const char *typeName, Oid typeNamespace, Oid relationOid, char relationKind, Oid ownerId, int16 internalSize, char typeType, char typeCategory, bool typePreferred, char typDelim, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, bool isImplicitArray, Oid arrayType, Oid baseType, const char *defaultTypeValue, char *defaultTypeBin, bool passedByValue, char alignment, char storage, int32 typeMod, int32 typNDims, bool typeNotNull, Oid typeCollation)
Definition: pg_type.c:193

◆ AddRelationNewConstraints()

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

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

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

References check_nested_generated_walker().

Referenced by cookDefault().

3019 {
3020  check_nested_generated_walker(node, pstate);
3021 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:2987

◆ check_nested_generated_walker()

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

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

2988 {
2989  ParseState *pstate = context;
2990 
2991  if (node == NULL)
2992  return false;
2993  else if (IsA(node, Var))
2994  {
2995  Var *var = (Var *) node;
2996  Oid relid;
2998 
2999  relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
3000  attnum = var->varattno;
3001 
3002  if (OidIsValid(relid) && AttributeNumberIsValid(attnum) && get_attgenerated(relid, attnum))
3003  ereport(ERROR,
3004  (errcode(ERRCODE_SYNTAX_ERROR),
3005  errmsg("cannot use generated column \"%s\" in column generation expression",
3006  get_attname(relid, attnum, false)),
3007  errdetail("A generated column cannot reference another generated column."),
3008  parser_errposition(pstate, var->location)));
3009 
3010  return false;
3011  }
3012  else
3014  (void *) context);
3015 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:2987
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
int errcode(int sqlerrcode)
Definition: elog.c:691
AttrNumber varattno
Definition: primnodes.h:186
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:181
#define OidIsValid(objectId)
Definition: c.h:706
#define ERROR
Definition: elog.h:43
int location
Definition: primnodes.h:196
int errdetail(const char *fmt,...)
Definition: elog.c:1035
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:886
Index varno
Definition: primnodes.h:184
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
int16 attnum
Definition: pg_attribute.h:79
#define ereport(elevel,...)
Definition: elog.h:155
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
int errmsg(const char *fmt,...)
Definition: elog.c:902
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
int16 AttrNumber
Definition: attnum.h:21
List * p_rtable
Definition: parse_node.h:180

◆ CheckAttributeNamesTypes()

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

Definition at line 489 of file heap.c.

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

Referenced by addRangeTableEntryForFunction(), and heap_create_with_catalog().

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

◆ CheckAttributeType()

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

Definition at line 581 of file heap.c.

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

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

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

◆ cookConstraint()

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

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

3114 {
3115  Node *expr;
3116 
3117  /*
3118  * Transform raw parsetree to executable expression.
3119  */
3120  expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
3121 
3122  /*
3123  * Make sure it yields a boolean result.
3124  */
3125  expr = coerce_to_boolean(pstate, expr, "CHECK");
3126 
3127  /*
3128  * Take care of collations.
3129  */
3130  assign_expr_collations(pstate, expr);
3131 
3132  /*
3133  * Make sure no outside relations are referred to (this is probably dead
3134  * code now that add_missing_from is history).
3135  */
3136  if (list_length(pstate->p_rtable) != 1)
3137  ereport(ERROR,
3138  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
3139  errmsg("only table \"%s\" can be referenced in check constraint",
3140  relname)));
3141 
3142  return expr;
3143 }
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:144
Definition: nodes.h:527
int errcode(int sqlerrcode)
Definition: elog.c:691
NameData relname
Definition: pg_class.h:38
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:155
static int list_length(const List *l)
Definition: pg_list.h:149
int errmsg(const char *fmt,...)
Definition: elog.c:902
List * p_rtable
Definition: parse_node.h:180
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)

◆ cookDefault()

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

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

3042 {
3043  Node *expr;
3044 
3045  Assert(raw_default != NULL);
3046 
3047  /*
3048  * Transform raw parsetree to executable expression.
3049  */
3050  expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
3051 
3052  if (attgenerated)
3053  {
3054  check_nested_generated(pstate, expr);
3055 
3056  if (contain_mutable_functions(expr))
3057  ereport(ERROR,
3058  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3059  errmsg("generation expression is not immutable")));
3060  }
3061  else
3062  {
3063  /*
3064  * For a default expression, transformExpr() should have rejected
3065  * column references.
3066  */
3067  Assert(!contain_var_clause(expr));
3068  }
3069 
3070  /*
3071  * Coerce the expression to the correct type and typmod, if given. This
3072  * should match the parser's processing of non-defaulted expressions ---
3073  * see transformAssignedExpr().
3074  */
3075  if (OidIsValid(atttypid))
3076  {
3077  Oid type_id = exprType(expr);
3078 
3079  expr = coerce_to_target_type(pstate, expr, type_id,
3080  atttypid, atttypmod,
3083  -1);
3084  if (expr == NULL)
3085  ereport(ERROR,
3086  (errcode(ERRCODE_DATATYPE_MISMATCH),
3087  errmsg("column \"%s\" is of type %s"
3088  " but default expression is of type %s",
3089  attname,
3091  format_type_be(type_id)),
3092  errhint("You will need to rewrite or cast the expression.")));
3093  }
3094 
3095  /*
3096  * Finally, take care of collations in the finished expression.
3097  */
3098  assign_expr_collations(pstate, expr);
3099 
3100  return expr;
3101 }
int errhint(const char *fmt,...)
Definition: elog.c:1149
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:144
Definition: nodes.h:527
int errcode(int sqlerrcode)
Definition: elog.c:691
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:706
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:77
Oid atttypid
Definition: pg_attribute.h:49
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:800
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static void check_nested_generated(ParseState *pstate, Node *node)
Definition: heap.c:3018
int errmsg(const char *fmt,...)
Definition: elog.c:902
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:357

◆ CopyStatistics()

void CopyStatistics ( Oid  fromrelid,
Oid  torelid 
)

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

3150 {
3151  HeapTuple tup;
3152  SysScanDesc scan;
3153  ScanKeyData key[1];
3154  Relation statrel;
3155 
3156  statrel = table_open(StatisticRelationId, RowExclusiveLock);
3157 
3158  /* Now search for stat records */
3159  ScanKeyInit(&key[0],
3160  Anum_pg_statistic_starelid,
3161  BTEqualStrategyNumber, F_OIDEQ,
3162  ObjectIdGetDatum(fromrelid));
3163 
3165  true, NULL, 1, key);
3166 
3167  while (HeapTupleIsValid((tup = systable_getnext(scan))))
3168  {
3169  Form_pg_statistic statform;
3170 
3171  /* make a modifiable copy */
3172  tup = heap_copytuple(tup);
3173  statform = (Form_pg_statistic) GETSTRUCT(tup);
3174 
3175  /* update the copy of the tuple and insert it */
3176  statform->starelid = torelid;
3177  CatalogTupleInsert(statrel, tup);
3178 
3179  heap_freetuple(tup);
3180  }
3181 
3182  systable_endscan(scan);
3183 
3184  table_close(statrel, RowExclusiveLock);
3185 }
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:569
#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:134
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define RowExclusiveLock
Definition: lockdefs.h:38
#define StatisticRelidAttnumInhIndexId
Definition: pg_statistic.h:139
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ DeleteAttributeTuples()

void DeleteAttributeTuples ( Oid  relid)

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

1571 {
1572  Relation attrel;
1573  SysScanDesc scan;
1574  ScanKeyData key[1];
1575  HeapTuple atttup;
1576 
1577  /* Grab an appropriate lock on the pg_attribute relation */
1578  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1579 
1580  /* Use the index to scan only attributes of the target relation */
1581  ScanKeyInit(&key[0],
1582  Anum_pg_attribute_attrelid,
1583  BTEqualStrategyNumber, F_OIDEQ,
1584  ObjectIdGetDatum(relid));
1585 
1586  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1587  NULL, 1, key);
1588 
1589  /* Delete all the matching tuples */
1590  while ((atttup = systable_getnext(scan)) != NULL)
1591  CatalogTupleDelete(attrel, &atttup->t_self);
1592 
1593  /* Clean up after the scan */
1594  systable_endscan(scan);
1595  table_close(attrel, RowExclusiveLock);
1596 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:198
#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 1541 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().

1542 {
1543  Relation pg_class_desc;
1544  HeapTuple tup;
1545 
1546  /* Grab an appropriate lock on the pg_class relation */
1547  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1548 
1549  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1550  if (!HeapTupleIsValid(tup))
1551  elog(ERROR, "cache lookup failed for relation %u", relid);
1552 
1553  /* delete the relation tuple from pg_class, and finish up */
1554  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1555 
1556  ReleaseSysCache(tup);
1557 
1558  table_close(pg_class_desc, RowExclusiveLock);
1559 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
#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 1607 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().

1608 {
1609  Relation attrel;
1610  SysScanDesc scan;
1611  ScanKeyData key[2];
1612  HeapTuple atttup;
1613 
1614  /* Grab an appropriate lock on the pg_attribute relation */
1615  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1616 
1617  /* Use the index to scan only system attributes of the target relation */
1618  ScanKeyInit(&key[0],
1619  Anum_pg_attribute_attrelid,
1620  BTEqualStrategyNumber, F_OIDEQ,
1621  ObjectIdGetDatum(relid));
1622  ScanKeyInit(&key[1],
1623  Anum_pg_attribute_attnum,
1624  BTLessEqualStrategyNumber, F_INT2LE,
1625  Int16GetDatum(0));
1626 
1627  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1628  NULL, 2, key);
1629 
1630  /* Delete all the matching tuples */
1631  while ((atttup = systable_getnext(scan)) != NULL)
1632  CatalogTupleDelete(attrel, &atttup->t_self);
1633 
1634  /* Clean up after the scan */
1635  systable_endscan(scan);
1636  table_close(attrel, RowExclusiveLock);
1637 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define Int16GetDatum(X)
Definition: postgres.h:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:198
#define RowExclusiveLock
Definition: lockdefs.h:38
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ heap_create()

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

Definition at line 294 of file heap.c.

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

Referenced by heap_create_with_catalog(), and index_create().

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

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

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

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

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

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

3290 {
3291  List *relations = NIL;
3292  ListCell *cell;
3293 
3294  /* Open relations for processing, and grab exclusive access on each */
3295  foreach(cell, relids)
3296  {
3297  Oid rid = lfirst_oid(cell);
3298  Relation rel;
3299 
3300  rel = table_open(rid, AccessExclusiveLock);
3301  relations = lappend(relations, rel);
3302  }
3303 
3304  /* Don't allow truncate on tables that are referenced by foreign keys */
3305  heap_truncate_check_FKs(relations, true);
3306 
3307  /* OK to do it */
3308  foreach(cell, relations)
3309  {
3310  Relation rel = lfirst(cell);
3311 
3312  /* Truncate the relation */
3313  heap_truncate_one_rel(rel);
3314 
3315  /* Close the relation, but keep exclusive lock on it until commit */
3316  table_close(rel, NoLock);
3317  }
3318 }
#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:3330
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3374
unsigned int Oid
Definition: postgres_ext.h:31
#define NoLock
Definition: lockdefs.h:34
List * lappend(List *list, void *datum)
Definition: list.c:321
#define lfirst(lc)
Definition: pg_list.h: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 3374 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().

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

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

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

3470 {
3471  List *result = NIL;
3472  List *oids;
3473  List *parent_cons;
3474  ListCell *cell;
3475  ScanKeyData key;
3476  Relation fkeyRel;
3477  SysScanDesc fkeyScan;
3478  HeapTuple tuple;
3479  bool restart;
3480 
3481  oids = list_copy(relationIds);
3482 
3483  /*
3484  * Must scan pg_constraint. Right now, it is a seqscan because there is
3485  * no available index on confrelid.
3486  */
3487  fkeyRel = table_open(ConstraintRelationId, AccessShareLock);
3488 
3489 restart:
3490  restart = false;
3491  parent_cons = NIL;
3492 
3493  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3494  NULL, 0, NULL);
3495 
3496  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3497  {
3499 
3500  /* Not a foreign key */
3501  if (con->contype != CONSTRAINT_FOREIGN)
3502  continue;
3503 
3504  /* Not referencing one of our list of tables */
3505  if (!list_member_oid(oids, con->confrelid))
3506  continue;
3507 
3508  /*
3509  * If this constraint has a parent constraint which we have not seen
3510  * yet, keep track of it for the second loop, below. Tracking parent
3511  * constraints allows us to climb up to the top-level level constraint
3512  * and look for all possible relations referencing the partitioned
3513  * table.
3514  */
3515  if (OidIsValid(con->conparentid) &&
3516  !list_member_oid(parent_cons, con->conparentid))
3517  parent_cons = lappend_oid(parent_cons, con->conparentid);
3518 
3519  /*
3520  * Add referencer to result, unless present in input list. (Don't
3521  * worry about dupes: we'll fix that below).
3522  */
3523  if (!list_member_oid(relationIds, con->conrelid))
3524  result = lappend_oid(result, con->conrelid);
3525  }
3526 
3527  systable_endscan(fkeyScan);
3528 
3529  /*
3530  * Process each parent constraint we found to add the list of referenced
3531  * relations by them to the oids list. If we do add any new such
3532  * relations, redo the first loop above. Also, if we see that the parent
3533  * constraint in turn has a parent, add that so that we process all
3534  * relations in a single additional pass.
3535  */
3536  foreach(cell, parent_cons)
3537  {
3538  Oid parent = lfirst_oid(cell);
3539 
3540  ScanKeyInit(&key,
3541  Anum_pg_constraint_oid,
3542  BTEqualStrategyNumber, F_OIDEQ,
3543  ObjectIdGetDatum(parent));
3544 
3545  fkeyScan = systable_beginscan(fkeyRel, ConstraintOidIndexId,
3546  true, NULL, 1, &key);
3547 
3548  tuple = systable_getnext(fkeyScan);
3549  if (HeapTupleIsValid(tuple))
3550  {
3552 
3553  /*
3554  * pg_constraint rows always appear for partitioned hierarchies
3555  * this way: on the each side of the constraint, one row appears
3556  * for each partition that points to the top-most table on the
3557  * other side.
3558  *
3559  * Because of this arrangement, we can correctly catch all
3560  * relevant relations by adding to 'parent_cons' all rows with
3561  * valid conparentid, and to the 'oids' list all rows with a zero
3562  * conparentid. If any oids are added to 'oids', redo the first
3563  * loop above by setting 'restart'.
3564  */
3565  if (OidIsValid(con->conparentid))
3566  parent_cons = list_append_unique_oid(parent_cons,
3567  con->conparentid);
3568  else if (!list_member_oid(oids, con->confrelid))
3569  {
3570  oids = lappend_oid(oids, con->confrelid);
3571  restart = true;
3572  }
3573  }
3574 
3575  systable_endscan(fkeyScan);
3576  }
3577 
3578  list_free(parent_cons);
3579  if (restart)
3580  goto restart;
3581 
3582  table_close(fkeyRel, AccessShareLock);
3583  list_free(oids);
3584 
3585  /* Now sort and de-duplicate the result list */
3586  list_sort(result, list_oid_cmp);
3587  list_deduplicate_oid(result);
3588 
3589  return result;
3590 }
#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:1217
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define AccessShareLock
Definition: lockdefs.h:36
List * list_copy(const List *oldlist)
Definition: list.c:1403
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define OidIsValid(objectId)
Definition: c.h:706
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1498
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ConstraintOidIndexId
void list_deduplicate_oid(List *list)
Definition: list.c:1325
#define InvalidOid
Definition: postgres_ext.h:36
FormData_pg_constraint * Form_pg_constraint
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:674
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1481
void list_free(List *list)
Definition: list.c:1376
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ heap_truncate_one_rel()

void heap_truncate_one_rel ( Relation  rel)

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

3331 {
3332  Oid toastrelid;
3333 
3334  /*
3335  * Truncate the relation. Partitioned tables have no storage, so there is
3336  * nothing to do for them here.
3337  */
3338  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3339  return;
3340 
3341  /* Truncate the underlying relation */
3343 
3344  /* If the relation has indexes, truncate the indexes too */
3346 
3347  /* If there is a toast table, truncate that too */
3348  toastrelid = rel->rd_rel->reltoastrelid;
3349  if (OidIsValid(toastrelid))
3350  {
3351  Relation toastrel = table_open(toastrelid, AccessExclusiveLock);
3352 
3354  RelationTruncateIndexes(toastrel);
3355  /* keep the lock... */
3356  table_close(toastrel, NoLock);
3357  }
3358 }
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:706
static void table_relation_nontransactional_truncate(Relation rel)
Definition: tableam.h:1414
#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:3241

◆ InsertPgAttributeTuples()

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

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

735 {
736  TupleTableSlot **slot;
737  TupleDesc td;
738  int nslots;
739  int natts = 0;
740  int slotCount = 0;
741  bool close_index = false;
742 
743  td = RelationGetDescr(pg_attribute_rel);
744 
745  /* Initialize the number of slots to use */
746  nslots = Min(tupdesc->natts,
748  slot = palloc(sizeof(TupleTableSlot *) * nslots);
749  for (int i = 0; i < nslots; i++)
751 
752  while (natts < tupdesc->natts)
753  {
754  Form_pg_attribute attrs = TupleDescAttr(tupdesc, natts);
755 
756  ExecClearTuple(slot[slotCount]);
757 
758  if (new_rel_oid != InvalidOid)
759  slot[slotCount]->tts_values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_rel_oid);
760  else
761  slot[slotCount]->tts_values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(attrs->attrelid);
762 
763  slot[slotCount]->tts_values[Anum_pg_attribute_attname - 1] = NameGetDatum(&attrs->attname);
764  slot[slotCount]->tts_values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(attrs->atttypid);
765  slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(attrs->attstattarget);
766  slot[slotCount]->tts_values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(attrs->attlen);
767  slot[slotCount]->tts_values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(attrs->attnum);
768  slot[slotCount]->tts_values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(attrs->attndims);
769  slot[slotCount]->tts_values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
770  slot[slotCount]->tts_values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(attrs->atttypmod);
771  slot[slotCount]->tts_values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(attrs->attbyval);
772  slot[slotCount]->tts_values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(attrs->attstorage);
773  slot[slotCount]->tts_values[Anum_pg_attribute_attalign - 1] = CharGetDatum(attrs->attalign);
774  slot[slotCount]->tts_values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(attrs->attnotnull);
775  slot[slotCount]->tts_values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(attrs->atthasdef);
776  slot[slotCount]->tts_values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(attrs->atthasmissing);
777  slot[slotCount]->tts_values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(attrs->attidentity);
778  slot[slotCount]->tts_values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(attrs->attgenerated);
779  slot[slotCount]->tts_values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(attrs->attisdropped);
780  slot[slotCount]->tts_values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(attrs->attislocal);
781  slot[slotCount]->tts_values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(attrs->attinhcount);
782  slot[slotCount]->tts_values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(attrs->attcollation);
783  if (attoptions && attoptions[natts] != (Datum) 0)
784  slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attoptions[natts];
785  else
786  slot[slotCount]->tts_isnull[Anum_pg_attribute_attoptions - 1] = true;
787 
788  /* start out with empty permissions and empty options */
789  slot[slotCount]->tts_isnull[Anum_pg_attribute_attacl - 1] = true;
790  slot[slotCount]->tts_isnull[Anum_pg_attribute_attfdwoptions - 1] = true;
791  slot[slotCount]->tts_isnull[Anum_pg_attribute_attmissingval - 1] = true;
792 
793  ExecStoreVirtualTuple(slot[slotCount]);
794  slotCount++;
795 
796  /*
797  * If slots are full or the end of processing has been reached, insert
798  * a batch of tuples.
799  */
800  if (slotCount == nslots || natts == tupdesc->natts - 1)
801  {
802  /* fetch index info only when we know we need it */
803  if (!indstate)
804  {
805  indstate = CatalogOpenIndexes(pg_attribute_rel);
806  close_index = true;
807  }
808 
809  /* insert the new tuples and update the indexes */
810  CatalogTuplesMultiInsertWithInfo(pg_attribute_rel, slot, slotCount,
811  indstate);
812  slotCount = 0;
813  }
814 
815  natts++;
816  }
817 
818  if (close_index)
819  CatalogCloseIndexes(indstate);
820  for (int i = 0; i < nslots; i++)
822  pfree(slot);
823 }
#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:982
#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:261
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:193
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:177
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 911 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().

916 {
917  Form_pg_class rd_rel = new_rel_desc->rd_rel;
918  Datum values[Natts_pg_class];
919  bool nulls[Natts_pg_class];
920  HeapTuple tup;
921 
922  /* This is a tad tedious, but way cleaner than what we used to do... */
923  memset(values, 0, sizeof(values));
924  memset(nulls, false, sizeof(nulls));
925 
926  values[Anum_pg_class_oid - 1] = ObjectIdGetDatum(new_rel_oid);
927  values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
928  values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
929  values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
930  values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
931  values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
932  values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
933  values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
934  values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
935  values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
936  values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
937  values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
938  values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
939  values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
940  values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
941  values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
942  values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
943  values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
944  values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
945  values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
946  values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
947  values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
948  values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
949  values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
950  values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
951  values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
952  values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
953  values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite);
954  values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
955  values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
956  if (relacl != (Datum) 0)
957  values[Anum_pg_class_relacl - 1] = relacl;
958  else
959  nulls[Anum_pg_class_relacl - 1] = true;
960  if (reloptions != (Datum) 0)
961  values[Anum_pg_class_reloptions - 1] = reloptions;
962  else
963  nulls[Anum_pg_class_reloptions - 1] = true;
964 
965  /* relpartbound is set by updating this tuple, if necessary */
966  nulls[Anum_pg_class_relpartbound - 1] = true;
967 
968  tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
969 
970  /* finally insert the new tuple, update the indexes, and clean up */
971  CatalogTupleInsert(pg_class_desc, tup);
972 
973  heap_freetuple(tup);
974 }
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:221

◆ MergeWithExistingConstraint()

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

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

2807 {
2808  bool found;
2809  Relation conDesc;
2810  SysScanDesc conscan;
2811  ScanKeyData skey[3];
2812  HeapTuple tup;
2813 
2814  /* Search for a pg_constraint entry with same name and relation */
2815  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
2816 
2817  found = false;
2818 
2819  ScanKeyInit(&skey[0],
2820  Anum_pg_constraint_conrelid,
2821  BTEqualStrategyNumber, F_OIDEQ,
2823  ScanKeyInit(&skey[1],
2824  Anum_pg_constraint_contypid,
2825  BTEqualStrategyNumber, F_OIDEQ,
2827  ScanKeyInit(&skey[2],
2828  Anum_pg_constraint_conname,
2829  BTEqualStrategyNumber, F_NAMEEQ,
2830  CStringGetDatum(ccname));
2831 
2832  conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId, true,
2833  NULL, 3, skey);
2834 
2835  /* There can be at most one matching row */
2836  if (HeapTupleIsValid(tup = systable_getnext(conscan)))
2837  {
2839 
2840  /* Found it. Conflicts if not identical check constraint */
2841  if (con->contype == CONSTRAINT_CHECK)
2842  {
2843  Datum val;
2844  bool isnull;
2845 
2846  val = fastgetattr(tup,
2847  Anum_pg_constraint_conbin,
2848  conDesc->rd_att, &isnull);
2849  if (isnull)
2850  elog(ERROR, "null conbin for rel %s",
2852  if (equal(expr, stringToNode(TextDatumGetCString(val))))
2853  found = true;
2854  }
2855 
2856  /*
2857  * If the existing constraint is purely inherited (no local
2858  * definition) then interpret addition of a local constraint as a
2859  * legal merge. This allows ALTER ADD CONSTRAINT on parent and child
2860  * tables to be given in either order with same end state. However if
2861  * the relation is a partition, all inherited constraints are always
2862  * non-local, including those that were merged.
2863  */
2864  if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
2865  allow_merge = true;
2866 
2867  if (!found || !allow_merge)
2868  ereport(ERROR,
2870  errmsg("constraint \"%s\" for relation \"%s\" already exists",
2871  ccname, RelationGetRelationName(rel))));
2872 
2873  /* If the child constraint is "no inherit" then cannot merge */
2874  if (con->connoinherit)
2875  ereport(ERROR,
2876  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2877  errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
2878  ccname, RelationGetRelationName(rel))));
2879 
2880  /*
2881  * Must not change an existing inherited constraint to "no inherit"
2882  * status. That's because inherited constraints should be able to
2883  * propagate to lower-level children.
2884  */
2885  if (con->coninhcount > 0 && is_no_inherit)
2886  ereport(ERROR,
2887  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2888  errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
2889  ccname, RelationGetRelationName(rel))));
2890 
2891  /*
2892  * If the child constraint is "not valid" then cannot merge with a
2893  * valid parent constraint.
2894  */
2895  if (is_initially_valid && !con->convalidated)
2896  ereport(ERROR,
2897  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2898  errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
2899  ccname, RelationGetRelationName(rel))));
2900 
2901  /* OK to update the tuple */
2902  ereport(NOTICE,
2903  (errmsg("merging constraint \"%s\" with inherited definition",
2904  ccname)));
2905 
2906  tup = heap_copytuple(tup);
2907  con = (Form_pg_constraint) GETSTRUCT(tup);
2908 
2909  /*
2910  * In case of partitions, an inherited constraint must be inherited
2911  * only once since it cannot have multiple parents and it is never
2912  * considered local.
2913  */
2914  if (rel->rd_rel->relispartition)
2915  {
2916  con->coninhcount = 1;
2917  con->conislocal = false;
2918  }
2919  else
2920  {
2921  if (is_local)
2922  con->conislocal = true;
2923  else
2924  con->coninhcount++;
2925  }
2926 
2927  if (is_no_inherit)
2928  {
2929  Assert(is_local);
2930  con->connoinherit = true;
2931  }
2932 
2933  CatalogTupleUpdate(conDesc, &tup->t_self, tup);
2934  }
2935 
2936  systable_endscan(conscan);
2937  table_close(conDesc, RowExclusiveLock);
2938 
2939  return found;
2940 }
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:569
#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:3028
int errcode(int sqlerrcode)
Definition: elog.c:691
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:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
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:87
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:800
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
int errmsg(const char *fmt,...)
Definition: elog.c:902
#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 2061 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().

2062 {
2063  Relation attr_rel;
2064  Oid relid = RelationGetRelid(rel);
2065  int natts = RelationGetNumberOfAttributes(rel);
2066  int attnum;
2067  Datum repl_val[Natts_pg_attribute];
2068  bool repl_null[Natts_pg_attribute];
2069  bool repl_repl[Natts_pg_attribute];
2070  Form_pg_attribute attrtuple;
2071  HeapTuple tuple,
2072  newtuple;
2073 
2074  memset(repl_val, 0, sizeof(repl_val));
2075  memset(repl_null, false, sizeof(repl_null));
2076  memset(repl_repl, false, sizeof(repl_repl));
2077 
2078  repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
2079  repl_null[Anum_pg_attribute_attmissingval - 1] = true;
2080 
2081  repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
2082  repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
2083 
2084 
2085  /* Get a lock on pg_attribute */
2086  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
2087 
2088  /* process each non-system attribute, including any dropped columns */
2089  for (attnum = 1; attnum <= natts; attnum++)
2090  {
2091  tuple = SearchSysCache2(ATTNUM,
2092  ObjectIdGetDatum(relid),
2093  Int16GetDatum(attnum));
2094  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
2095  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2096  attnum, relid);
2097 
2098  attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
2099 
2100  /* ignore any where atthasmissing is not true */
2101  if (attrtuple->atthasmissing)
2102  {
2103  newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
2104  repl_val, repl_null, repl_repl);
2105 
2106  CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
2107 
2108  heap_freetuple(newtuple);
2109  }
2110 
2111  ReleaseSysCache(tuple);
2112  }
2113 
2114  /*
2115  * Our update of the pg_attribute rows will force a relcache rebuild, so
2116  * there's nothing else to do here.
2117  */
2118  table_close(attr_rel, RowExclusiveLock);
2119 }
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:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
#define BoolGetDatum(X)
Definition: postgres.h:402
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1126
#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 1508 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().

1509 {
1510  Relation catalogRelation;
1511  SysScanDesc scan;
1512  ScanKeyData key;
1513  HeapTuple tuple;
1514 
1515  catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
1516 
1517  ScanKeyInit(&key,
1518  Anum_pg_inherits_inhrelid,
1519  BTEqualStrategyNumber, F_OIDEQ,
1520  ObjectIdGetDatum(relid));
1521 
1522  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
1523  NULL, 1, &key);
1524 
1525  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1526  CatalogTupleDelete(catalogRelation, &tuple->t_self);
1527 
1528  systable_endscan(scan);
1529  table_close(catalogRelation, RowExclusiveLock);
1530 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define InheritsRelidSeqnoIndexId
Definition: pg_inherits.h:47
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#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 3241 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().

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

1763 {
1764  Relation attrdef_rel;
1765  ScanKeyData scankeys[2];
1766  SysScanDesc scan;
1767  HeapTuple tuple;
1768  bool found = false;
1769 
1770  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1771 
1772  ScanKeyInit(&scankeys[0],
1773  Anum_pg_attrdef_adrelid,
1774  BTEqualStrategyNumber, F_OIDEQ,
1775  ObjectIdGetDatum(relid));
1776  ScanKeyInit(&scankeys[1],
1777  Anum_pg_attrdef_adnum,
1778  BTEqualStrategyNumber, F_INT2EQ,
1780 
1781  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1782  NULL, 2, scankeys);
1783 
1784  /* There should be at most one matching tuple, but we loop anyway */
1785  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1786  {
1787  ObjectAddress object;
1788  Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
1789 
1790  object.classId = AttrDefaultRelationId;
1791  object.objectId = attrtuple->oid;
1792  object.objectSubId = 0;
1793 
1794  performDeletion(&object, behavior,
1795  internal ? PERFORM_DELETION_INTERNAL : 0);
1796 
1797  found = true;
1798  }
1799 
1800  systable_endscan(scan);
1801  table_close(attrdef_rel, RowExclusiveLock);
1802 
1803  if (complain && !found)
1804  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1805  relid, attnum);
1806 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define AttrDefaultIndexId
Definition: pg_attrdef.h:52
#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:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#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:47
int16 attnum
Definition: pg_attribute.h:79
#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:134

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

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

1817 {
1818  Relation attrdef_rel;
1819  Relation attr_rel;
1820  Relation myrel;
1821  ScanKeyData scankeys[1];
1822  SysScanDesc scan;
1823  HeapTuple tuple;
1824  Oid myrelid;
1825  AttrNumber myattnum;
1826 
1827  /* Grab an appropriate lock on the pg_attrdef relation */
1828  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1829 
1830  /* Find the pg_attrdef tuple */
1831  ScanKeyInit(&scankeys[0],
1832  Anum_pg_attrdef_oid,
1833  BTEqualStrategyNumber, F_OIDEQ,
1834  ObjectIdGetDatum(attrdefId));
1835 
1836  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1837  NULL, 1, scankeys);
1838 
1839  tuple = systable_getnext(scan);
1840  if (!HeapTupleIsValid(tuple))
1841  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1842 
1843  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1844  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1845 
1846  /* Get an exclusive lock on the relation owning the attribute */
1847  myrel = relation_open(myrelid, AccessExclusiveLock);
1848 
1849  /* Now we can delete the pg_attrdef row */
1850  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1851 
1852  systable_endscan(scan);
1853  table_close(attrdef_rel, RowExclusiveLock);
1854 
1855  /* Fix the pg_attribute row */
1856  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1857 
1858  tuple = SearchSysCacheCopy2(ATTNUM,
1859  ObjectIdGetDatum(myrelid),
1860  Int16GetDatum(myattnum));
1861  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1862  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1863  myattnum, myrelid);
1864 
1865  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1866 
1867  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1868 
1869  /*
1870  * Our update of the pg_attribute row will force a relcache rebuild, so
1871  * there's nothing else to do here.
1872  */
1873  table_close(attr_rel, RowExclusiveLock);
1874 
1875  /* Keep lock on attribute's rel until end of xact */
1876  relation_close(myrel, NoLock);
1877 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define Int16GetDatum(X)
Definition: postgres.h:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
#define AttrDefaultOidIndexId
Definition: pg_attrdef.h:54
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define elog(elevel,...)
Definition: elog.h: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:176
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
int16 AttrNumber
Definition: attnum.h:21
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RemoveAttributeById()

void RemoveAttributeById ( Oid  relid,
AttrNumber  attnum 
)

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

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

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

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

3726 {
3727  Relation rel;
3728  HeapTuple tuple;
3729 
3730  rel = table_open(PartitionedRelationId, RowExclusiveLock);
3731 
3732  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3733  if (!HeapTupleIsValid(tuple))
3734  elog(ERROR, "cache lookup failed for partition key of relation %u",
3735  relid);
3736 
3737  CatalogTupleDelete(rel, &tuple->t_self);
3738 
3739  ReleaseSysCache(tuple);
3741 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1115
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
#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 3194 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().

3195 {
3196  Relation pgstatistic;
3197  SysScanDesc scan;
3198  ScanKeyData key[2];
3199  int nkeys;
3200  HeapTuple tuple;
3201 
3202  pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
3203 
3204  ScanKeyInit(&key[0],
3205  Anum_pg_statistic_starelid,
3206  BTEqualStrategyNumber, F_OIDEQ,
3207  ObjectIdGetDatum(relid));
3208 
3209  if (attnum == 0)
3210  nkeys = 1;
3211  else
3212  {
3213  ScanKeyInit(&key[1],
3214  Anum_pg_statistic_staattnum,
3215  BTEqualStrategyNumber, F_INT2EQ,
3217  nkeys = 2;
3218  }
3219 
3220  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
3221  NULL, nkeys, key);
3222 
3223  /* we must loop even when attnum != 0, in case of inherited stats */
3224  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3225  CatalogTupleDelete(pgstatistic, &tuple->t_self);
3226 
3227  systable_endscan(scan);
3228 
3229  table_close(pgstatistic, RowExclusiveLock);
3230 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define Int16GetDatum(X)
Definition: postgres.h:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#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:139
int16 attnum
Definition: pg_attribute.h:79
#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 2129 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().

2130 {
2131  Datum valuesAtt[Natts_pg_attribute];
2132  bool nullsAtt[Natts_pg_attribute];
2133  bool replacesAtt[Natts_pg_attribute];
2134  Datum missingval;
2135  Form_pg_attribute attStruct;
2136  Relation attrrel,
2137  tablerel;
2138  HeapTuple atttup,
2139  newtup;
2140 
2141  /* lock the table the attribute belongs to */
2142  tablerel = table_open(relid, AccessExclusiveLock);
2143 
2144  /* Lock the attribute row and get the data */
2145  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2146  atttup = SearchSysCacheAttName(relid, attname);
2147  if (!HeapTupleIsValid(atttup))
2148  elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2149  attname, relid);
2150  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2151 
2152  /* get an array value from the value string */
2153  missingval = OidFunctionCall3(F_ARRAY_IN,
2155  ObjectIdGetDatum(attStruct->atttypid),
2156  Int32GetDatum(attStruct->atttypmod));
2157 
2158  /* update the tuple - set atthasmissing and attmissingval */
2159  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2160  MemSet(nullsAtt, false, sizeof(nullsAtt));
2161  MemSet(replacesAtt, false, sizeof(replacesAtt));
2162 
2163  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
2164  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2165  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2166  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2167 
2168  newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2169  valuesAtt, nullsAtt, replacesAtt);
2170  CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
2171 
2172  /* clean up */
2173  ReleaseSysCache(atttup);
2174  table_close(attrrel, RowExclusiveLock);
2175  table_close(tablerel, AccessExclusiveLock);
2176 }
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:1004
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition: fmgr.h:668
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1163
#define BoolGetDatum(X)
Definition: postgres.h:402
static struct @143 value
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1256
#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 2953 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().

2954 {
2955  Relation relrel;
2956  HeapTuple reltup;
2957  Form_pg_class relStruct;
2958 
2959  relrel = table_open(RelationRelationId, RowExclusiveLock);
2960  reltup = SearchSysCacheCopy1(RELOID,
2962  if (!HeapTupleIsValid(reltup))
2963  elog(ERROR, "cache lookup failed for relation %u",
2964  RelationGetRelid(rel));
2965  relStruct = (Form_pg_class) GETSTRUCT(reltup);
2966 
2967  if (relStruct->relchecks != numchecks)
2968  {
2969  relStruct->relchecks = numchecks;
2970 
2971  CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
2972  }
2973  else
2974  {
2975  /* Skip the disk update, but force relcache inval anyway */
2977  }
2978 
2979  heap_freetuple(reltup);
2980  table_close(relrel, RowExclusiveLock);
2981 }
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:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
#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 2190 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().

2192 {
2193  char *adbin;
2194  Relation adrel;
2195  HeapTuple tuple;
2196  Datum values[4];
2197  static bool nulls[4] = {false, false, false, false};
2198  Relation attrrel;
2199  HeapTuple atttup;
2200  Form_pg_attribute attStruct;
2201  char attgenerated;
2202  Oid attrdefOid;
2203  ObjectAddress colobject,
2204  defobject;
2205 
2206  adrel = table_open(AttrDefaultRelationId, RowExclusiveLock);
2207 
2208  /*
2209  * Flatten expression to string form for storage.
2210  */
2211  adbin = nodeToString(expr);
2212 
2213  /*
2214  * Make the pg_attrdef entry.
2215  */
2216  attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId,
2217  Anum_pg_attrdef_oid);
2218  values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid);
2219  values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
2220  values[Anum_pg_attrdef_adnum - 1] = attnum;
2221  values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
2222 
2223  tuple = heap_form_tuple(adrel->rd_att, values, nulls);
2224  CatalogTupleInsert(adrel, tuple);
2225 
2226  defobject.classId = AttrDefaultRelationId;
2227  defobject.objectId = attrdefOid;
2228  defobject.objectSubId = 0;
2229 
2230  table_close(adrel, RowExclusiveLock);
2231 
2232  /* now can free some of the stuff allocated above */
2233  pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
2234  heap_freetuple(tuple);
2235  pfree(adbin);
2236 
2237  /*
2238  * Update the pg_attribute entry for the column to show that a default
2239  * exists.
2240  */
2241  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2242  atttup = SearchSysCacheCopy2(ATTNUM,
2245  if (!HeapTupleIsValid(atttup))
2246  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2247  attnum, RelationGetRelid(rel));
2248  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2249  attgenerated = attStruct->attgenerated;
2250  if (!attStruct->atthasdef)
2251  {
2252  Form_pg_attribute defAttStruct;
2253 
2254  ExprState *exprState;
2255  Expr *expr2 = (Expr *) expr;
2256  EState *estate = NULL;
2257  ExprContext *econtext;
2258  Datum valuesAtt[Natts_pg_attribute];
2259  bool nullsAtt[Natts_pg_attribute];
2260  bool replacesAtt[Natts_pg_attribute];
2261  Datum missingval = (Datum) 0;
2262  bool missingIsNull = true;
2263 
2264  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2265  MemSet(nullsAtt, false, sizeof(nullsAtt));
2266  MemSet(replacesAtt, false, sizeof(replacesAtt));
2267  valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2268  replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2269 
2270  if (add_column_mode && !attgenerated)
2271  {
2272  expr2 = expression_planner(expr2);
2273  estate = CreateExecutorState();
2274  exprState = ExecPrepareExpr(expr2, estate);
2275  econtext = GetPerTupleExprContext(estate);
2276 
2277  missingval = ExecEvalExpr(exprState, econtext,
2278  &missingIsNull);
2279 
2280  FreeExecutorState(estate);
2281 
2282  defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1);
2283 
2284  if (missingIsNull)
2285  {
2286  /* if the default evaluates to NULL, just store a NULL array */
2287  missingval = (Datum) 0;
2288  }
2289  else
2290  {
2291  /* otherwise make a one-element array of the value */
2292  missingval = PointerGetDatum(construct_array(&missingval,
2293  1,
2294  defAttStruct->atttypid,
2295  defAttStruct->attlen,
2296  defAttStruct->attbyval,
2297  defAttStruct->attalign));
2298  }
2299 
2300  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
2301  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2302  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2303  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2304  nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull;
2305  }
2306  atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2307  valuesAtt, nullsAtt, replacesAtt);
2308 
2309  CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
2310 
2311  if (!missingIsNull)
2312  pfree(DatumGetPointer(missingval));
2313 
2314  }
2315  table_close(attrrel, RowExclusiveLock);
2316  heap_freetuple(atttup);
2317 
2318  /*
2319  * Make a dependency so that the pg_attrdef entry goes away if the column
2320  * (or whole table) is deleted.
2321  */
2322  colobject.classId = RelationRelationId;
2323  colobject.objectId = RelationGetRelid(rel);
2324  colobject.objectSubId = attnum;
2325 
2326  recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
2327 
2328  /*
2329  * Record dependencies on objects used in the expression, too.
2330  */
2331  if (attgenerated)
2332  {
2333  /*
2334  * Generated column: Dropping anything that the generation expression
2335  * refers to automatically drops the generated column.
2336  */
2337  recordDependencyOnSingleRelExpr(&colobject, expr, RelationGetRelid(rel),
2339  DEPENDENCY_AUTO, false, false);
2340  }
2341  else
2342  {
2343  /*
2344  * Normal default: Dropping anything that the default refers to
2345  * requires CASCADE and drops the default only.
2346  */
2347  recordDependencyOnSingleRelExpr(&defobject, expr, RelationGetRelid(rel),
2349  DEPENDENCY_NORMAL, false, false);
2350  }
2351 
2352  /*
2353  * Post creation hook for attribute defaults.
2354  *
2355  * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
2356  * couple of deletion/creation of the attribute's default entry, so the
2357  * callee should check existence of an older version of this entry if it
2358  * needs to distinguish.
2359  */
2360  InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
2361  RelationGetRelid(rel), attnum, is_internal);
2362 
2363  return attrdefOid;
2364 }
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:6166
#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:3313
#define MemSet(start, val, len)
Definition: c.h:1004
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:491
void FreeExecutorState(EState *estate)
Definition: execUtils.c:185
#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:43
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:193
EState * CreateExecutorState(void)
Definition: execUtils.c:89
uintptr_t Datum
Definition: postgres.h:367
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:153
TupleDesc rd_att
Definition: rel.h:111
int16 attnum
Definition: pg_attribute.h:79
#define AttrDefaultOidIndexId
Definition: pg_attrdef.h:54
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#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:86
char * nodeToString(const void *obj)
Definition: outfuncs.c:4357
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:176
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define RelationGetRelid(relation)
Definition: rel.h:457
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ StoreConstraints()

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

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

2484 {
2485  int numchecks = 0;
2486  ListCell *lc;
2487 
2488  if (cooked_constraints == NIL)
2489  return; /* nothing to do */
2490 
2491  /*
2492  * Deparsing of constraint expressions will fail unless the just-created
2493  * pg_attribute tuples for this relation are made visible. So, bump the
2494  * command counter. CAUTION: this will cause a relcache entry rebuild.
2495  */
2497 
2498  foreach(lc, cooked_constraints)
2499  {
2500  CookedConstraint *con = (CookedConstraint *) lfirst(lc);
2501 
2502  switch (con->contype)
2503  {
2504  case CONSTR_DEFAULT:
2505  con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
2506  is_internal, false);
2507  break;
2508  case CONSTR_CHECK:
2509  con->conoid =
2510  StoreRelCheck(rel, con->name, con->expr,
2511  !con->skip_validation, con->is_local,
2512  con->inhcount, con->is_no_inherit,
2513  is_internal);
2514  numchecks++;
2515  break;
2516  default:
2517  elog(ERROR, "unrecognized constraint type: %d",
2518  (int) con->contype);
2519  }
2520  }
2521 
2522  if (numchecks > 0)
2523  SetRelationNumChecks(rel, numchecks);
2524 }
#define NIL
Definition: pg_list.h:65
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2953
bool is_no_inherit
Definition: heap.h:45
AttrNumber attnum
Definition: heap.h:40
#define ERROR
Definition: elog.h:43
int inhcount
Definition: heap.h:44
bool skip_validation
Definition: heap.h:42
ConstrType contype
Definition: heap.h:37
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal, bool add_column_mode)
Definition: heap.c:2190
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:2375
bool is_local
Definition: heap.h:43

◆ StorePartitionBound()

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

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

3757 {
3758  Relation classRel;
3759  HeapTuple tuple,
3760  newtuple;
3761  Datum new_val[Natts_pg_class];
3762  bool new_null[Natts_pg_class],
3763  new_repl[Natts_pg_class];
3764  Oid defaultPartOid;
3765 
3766  /* Update pg_class tuple */
3767  classRel = table_open(RelationRelationId, RowExclusiveLock);
3768  tuple = SearchSysCacheCopy1(RELOID,
3770  if (!HeapTupleIsValid(tuple))
3771  elog(ERROR, "cache lookup failed for relation %u",
3772  RelationGetRelid(rel));
3773 
3774 #ifdef USE_ASSERT_CHECKING
3775  {
3776  Form_pg_class classForm;
3777  bool isnull;
3778 
3779  classForm = (Form_pg_class) GETSTRUCT(tuple);
3780  Assert(!classForm->relispartition);
3781  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3782  &isnull);
3783  Assert(isnull);
3784  }
3785 #endif
3786 
3787  /* Fill in relpartbound value */
3788  memset(new_val, 0, sizeof(new_val));
3789  memset(new_null, false, sizeof(new_null));
3790  memset(new_repl, false, sizeof(new_repl));
3791  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3792  new_null[Anum_pg_class_relpartbound - 1] = false;
3793  new_repl[Anum_pg_class_relpartbound - 1] = true;
3794  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3795  new_val, new_null, new_repl);
3796  /* Also set the flag */
3797  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3798  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3799  heap_freetuple(newtuple);
3800  table_close(classRel, RowExclusiveLock);
3801 
3802  /*
3803  * If we're storing bounds for the default partition, update
3804  * pg_partitioned_table too.
3805  */
3806  if (bound->is_default)
3808  RelationGetRelid(rel));
3809 
3810  /* Make these updates visible */
3812 
3813  /*
3814  * The partition constraint for the default partition depends on the
3815  * partition bounds of every other partition, so we must invalidate the
3816  * relcache entry for that partition every time a partition is added or
3817  * removed.
3818  */
3819  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3820  if (OidIsValid(defaultPartOid))
3821  CacheInvalidateRelcacheByRelid(defaultPartOid);
3822 
3823  CacheInvalidateRelcache(parent);
3824 }
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:706
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
PartitionDesc RelationGetPartitionDesc(Relation rel)
Definition: partdesc.c: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:1376
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:800
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
#define elog(elevel,...)
Definition: elog.h:228
#define CStringGetTextDatum(s)
Definition: builtins.h:86
char * nodeToString(const void *obj)
Definition: outfuncs.c:4357
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 3597 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().

3604 {
3605  int i;
3606  int2vector *partattrs_vec;
3607  oidvector *partopclass_vec;
3608  oidvector *partcollation_vec;
3609  Datum partexprDatum;
3610  Relation pg_partitioned_table;
3611  HeapTuple tuple;
3612  Datum values[Natts_pg_partitioned_table];
3613  bool nulls[Natts_pg_partitioned_table];
3614  ObjectAddress myself;
3615  ObjectAddress referenced;
3616  ObjectAddresses *addrs;
3617 
3618  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3619 
3620  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3621  partattrs_vec = buildint2vector(partattrs, partnatts);
3622  partopclass_vec = buildoidvector(partopclass, partnatts);
3623  partcollation_vec = buildoidvector(partcollation, partnatts);
3624 
3625  /* Convert the expressions (if any) to a text datum */
3626  if (partexprs)
3627  {
3628  char *exprString;
3629 
3630  exprString = nodeToString(partexprs);
3631  partexprDatum = CStringGetTextDatum(exprString);
3632  pfree(exprString);
3633  }
3634  else
3635  partexprDatum = (Datum) 0;
3636 
3637  pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
3638 
3639  MemSet(nulls, false, sizeof(nulls));
3640 
3641  /* Only this can ever be NULL */
3642  if (!partexprDatum)
3643  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3644 
3645  values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
3646  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3647  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3648  values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
3649  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3650  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3651  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3652  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3653 
3654  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3655 
3656  CatalogTupleInsert(pg_partitioned_table, tuple);
3657  table_close(pg_partitioned_table, RowExclusiveLock);
3658 
3659  /* Mark this relation as dependent on a few things as follows */
3660  addrs = new_object_addresses();
3661  ObjectAddressSet(myself, RelationRelationId, RelationGetRelid(rel));
3662 
3663  /* Operator class and collation per key column */
3664  for (i = 0; i < partnatts; i++)
3665  {
3666  ObjectAddressSet(referenced, OperatorClassRelationId, partopclass[i]);
3667  add_exact_object_address(&referenced, addrs);
3668 
3669  /* The default collation is pinned, so don't bother recording it */
3670  if (OidIsValid(partcollation[i]) &&
3671  partcollation[i] != DEFAULT_COLLATION_OID)
3672  {
3673  ObjectAddressSet(referenced, CollationRelationId, partcollation[i]);
3674  add_exact_object_address(&referenced, addrs);
3675  }
3676  }
3677 
3679  free_object_addresses(addrs);
3680 
3681  /*
3682  * The partitioning columns are made internally dependent on the table,
3683  * because we cannot drop any of them without dropping the whole table.
3684  * (ATExecDropColumn independently enforces that, but it's not bulletproof
3685  * so we need the dependencies too.)
3686  */
3687  for (i = 0; i < partnatts; i++)
3688  {
3689  if (partattrs[i] == 0)
3690  continue; /* ignore expressions here */
3691 
3692  ObjectAddressSubSet(referenced, RelationRelationId,
3693  RelationGetRelid(rel), partattrs[i]);
3694  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
3695  }
3696 
3697  /*
3698  * Also consider anything mentioned in partition expressions. External
3699  * references (e.g. functions) get NORMAL dependencies. Table columns
3700  * mentioned in the expressions are handled the same as plain partitioning
3701  * columns, i.e. they become internally dependent on the whole table.
3702  */
3703  if (partexprs)
3705  (Node *) partexprs,
3706  RelationGetRelid(rel),
3709  true /* reverse the self-deps */ ,
3710  false /* don't track versions */ );
3711 
3712  /*
3713  * We must invalidate the relcache so that the next
3714  * CommandCounterIncrement() will cause the same to be rebuilt using the
3715  * information in just created catalog entry.
3716  */
3718 }
Definition: c.h:656
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:2803
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:114
#define Int16GetDatum(X)
Definition: postgres.h:451
Definition: nodes.h:527
#define MemSet(start, val, len)
Definition: c.h:1004
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:2594
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2539
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2835
Form_pg_class rd_rel
Definition: rel.h:110
#define OidIsValid(objectId)
Definition: c.h:706
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:645
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:800
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:86
char * nodeToString(const void *obj)
Definition: outfuncs.c:4357
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:221

◆ StoreRelCheck()

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

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

2378 {
2379  char *ccbin;
2380  List *varList;
2381  int keycount;
2382  int16 *attNos;
2383  Oid constrOid;
2384 
2385  /*
2386  * Flatten expression to string form for storage.
2387  */
2388  ccbin = nodeToString(expr);
2389 
2390  /*
2391  * Find columns of rel that are used in expr
2392  *
2393  * NB: pull_var_clause is okay here only because we don't allow subselects
2394  * in check constraints; it would fail to examine the contents of
2395  * subselects.
2396  */
2397  varList = pull_var_clause(expr, 0);
2398  keycount = list_length(varList);
2399 
2400  if (keycount > 0)
2401  {
2402  ListCell *vl;
2403  int i = 0;
2404 
2405  attNos = (int16 *) palloc(keycount * sizeof(int16));
2406  foreach(vl, varList)
2407  {
2408  Var *var = (Var *) lfirst(vl);
2409  int j;
2410 
2411  for (j = 0; j < i; j++)
2412  if (attNos[j] == var->varattno)
2413  break;
2414  if (j == i)
2415  attNos[i++] = var->varattno;
2416  }
2417  keycount = i;
2418  }
2419  else
2420  attNos = NULL;
2421 
2422  /*
2423  * Partitioned tables do not contain any rows themselves, so a NO INHERIT
2424  * constraint makes no sense.
2425  */
2426  if (is_no_inherit &&
2427  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2428  ereport(ERROR,
2429  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2430  errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
2431  RelationGetRelationName(rel))));
2432 
2433  /*
2434  * Create the Check Constraint
2435  */
2436  constrOid =
2437  CreateConstraintEntry(ccname, /* Constraint Name */
2438  RelationGetNamespace(rel), /* namespace */
2439  CONSTRAINT_CHECK, /* Constraint Type */
2440  false, /* Is Deferrable */
2441  false, /* Is Deferred */
2442  is_validated,
2443  InvalidOid, /* no parent constraint */
2444  RelationGetRelid(rel), /* relation */
2445  attNos, /* attrs in the constraint */
2446  keycount, /* # key attrs in the constraint */
2447  keycount, /* # total attrs in the constraint */
2448  InvalidOid, /* not a domain constraint */
2449  InvalidOid, /* no associated index */
2450  InvalidOid, /* Foreign key fields */
2451  NULL,
2452  NULL,
2453  NULL,
2454  NULL,
2455  0,
2456  ' ',
2457  ' ',
2458  ' ',
2459  NULL, /* not an exclusion constraint */
2460  expr, /* Tree form of check constraint */
2461  ccbin, /* Binary form of check constraint */
2462  is_local, /* conislocal */
2463  inhcount, /* coninhcount */
2464  is_no_inherit, /* connoinherit */
2465  is_internal); /* internally constructed? */
2466 
2467  pfree(ccbin);
2468 
2469  return constrOid;
2470 }
signed short int16
Definition: c.h:416
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:691
AttrNumber varattno
Definition: primnodes.h:186
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
Form_pg_class rd_rel
Definition: rel.h: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:43
#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:902
int i
char * nodeToString(const void *obj)
Definition: outfuncs.c:4357
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:730
NameData attname
Definition: pg_attribute.h:40
FormData_pg_attribute
Definition: pg_attribute.h:177
static const FormData_pg_attribute * SysAtt[]
Definition: heap.c:241
#define NameStr(name)
Definition: c.h:677

◆ 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:730
#define ERROR
Definition: elog.h:43
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:116
bool attnotnull
Definition: pg_attribute.h:125
bool attbyval
Definition: pg_attribute.h:108
char attalign
Definition: pg_attribute.h:122
int16 attnum
Definition: pg_attribute.h:79
struct ItemPointerData ItemPointerData