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/rel.h"
#include "utils/ruleutils.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for heap.c:

Go to the source code of this file.

Functions

static void AddNewRelationTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, Oid reloftype, Oid relowner, char relkind, TransactionId relfrozenxid, TransactionId relminmxid, Datum relacl, Datum reloptions)
 
static ObjectAddress AddNewRelationType (const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, Oid ownerid, Oid new_row_type, Oid new_array_type)
 
static void RelationRemoveInheritance (Oid relid)
 
static Oid StoreRelCheck (Relation rel, const char *ccname, Node *expr, bool is_validated, bool is_local, int inhcount, bool is_no_inherit, bool is_internal)
 
static void StoreConstraints (Relation rel, List *cooked_constraints, bool is_internal)
 
static bool MergeWithExistingConstraint (Relation rel, const char *ccname, Node *expr, bool allow_merge, bool is_local, bool is_initially_valid, bool is_no_inherit)
 
static void SetRelationNumChecks (Relation rel, int numchecks)
 
static NodecookConstraint (ParseState *pstate, Node *raw_constraint, char *relname)
 
const FormData_pg_attributeSystemAttributeDefinition (AttrNumber attno)
 
const FormData_pg_attributeSystemAttributeByName (const char *attname)
 
Relation heap_create (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid relfilenode, Oid accessmtd, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods, TransactionId *relfrozenxid, MultiXactId *relminmxid)
 
void CheckAttributeNamesTypes (TupleDesc tupdesc, char relkind, int flags)
 
void CheckAttributeType (const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
 
void InsertPgAttributeTuple (Relation pg_attribute_rel, Form_pg_attribute new_attribute, CatalogIndexState indstate)
 
static void AddNewAttributeTuples (Oid new_rel_oid, TupleDesc tupdesc, char relkind)
 
void InsertPgClassTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
 
Oid heap_create_with_catalog (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid reltypeid, Oid reloftypeid, Oid ownerid, Oid accessmtd, TupleDesc tupdesc, List *cooked_constraints, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, OnCommitAction oncommit, Datum reloptions, bool use_user_acl, bool allow_system_table_mods, bool is_internal, Oid relrewrite, ObjectAddress *typaddress)
 
void DeleteRelationTuple (Oid relid)
 
void DeleteAttributeTuples (Oid relid)
 
void DeleteSystemAttributeTuples (Oid relid)
 
void RemoveAttributeById (Oid relid, AttrNumber attnum)
 
void RemoveAttrDefault (Oid relid, AttrNumber attnum, DropBehavior behavior, bool complain, bool internal)
 
void RemoveAttrDefaultById (Oid attrdefId)
 
void heap_drop_with_catalog (Oid relid)
 
void RelationClearMissing (Relation rel)
 
void SetAttrMissing (Oid relid, char *attname, char *value)
 
Oid StoreAttrDefault (Relation rel, AttrNumber attnum, Node *expr, bool is_internal, bool add_column_mode)
 
ListAddRelationNewConstraints (Relation rel, List *newColDefaults, List *newConstraints, bool allow_merge, bool is_local, bool is_internal, const char *queryString)
 
static bool check_nested_generated_walker (Node *node, void *context)
 
static void check_nested_generated (ParseState *pstate, Node *node)
 
NodecookDefault (ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname, char attgenerated)
 
void RemoveStatistics (Oid relid, AttrNumber attnum)
 
static void RelationTruncateIndexes (Relation heapRelation)
 
void heap_truncate (List *relids)
 
void heap_truncate_one_rel (Relation rel)
 
void heap_truncate_check_FKs (List *relations, bool tempTables)
 
Listheap_truncate_find_FKs (List *relationIds)
 
void StorePartitionKey (Relation rel, char strategy, int16 partnatts, AttrNumber *partattrs, List *partexprs, Oid *partopclass, Oid *partcollation)
 
void RemovePartitionKeyByRelId (Oid relid)
 
void StorePartitionBound (Relation rel, Relation parent, PartitionBoundSpec *bound)
 

Variables

Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid
 
Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid
 
static const FormData_pg_attribute a1
 
static const FormData_pg_attribute a2
 
static const FormData_pg_attribute a3
 
static const FormData_pg_attribute a4
 
static const FormData_pg_attribute a5
 
static const FormData_pg_attribute a6
 
static const FormData_pg_attributeSysAtt [] = {&a1, &a2, &a3, &a4, &a5, &a6}
 

Function Documentation

◆ AddNewAttributeTuples()

static void AddNewAttributeTuples ( Oid  new_rel_oid,
TupleDesc  tupdesc,
char  relkind 
)
static

Definition at line 753 of file heap.c.

References CatalogCloseIndexes(), CatalogOpenIndexes(), ObjectAddress::classId, DEPENDENCY_NORMAL, FormData_pg_attribute, i, InsertPgAttributeTuple(), lengthof, TupleDescData::natts, ObjectAddress::objectId, ObjectAddress::objectSubId, OidIsValid, recordDependencyOn(), RowExclusiveLock, SysAtt, table_close(), table_open(), and TupleDescAttr.

Referenced by heap_create_with_catalog().

756 {
757  Form_pg_attribute attr;
758  int i;
759  Relation rel;
760  CatalogIndexState indstate;
761  int natts = tupdesc->natts;
762  ObjectAddress myself,
763  referenced;
764 
765  /*
766  * open pg_attribute and its indexes.
767  */
768  rel = table_open(AttributeRelationId, RowExclusiveLock);
769 
770  indstate = CatalogOpenIndexes(rel);
771 
772  /*
773  * First we add the user attributes. This is also a convenient place to
774  * add dependencies on their datatypes and collations.
775  */
776  for (i = 0; i < natts; i++)
777  {
778  attr = TupleDescAttr(tupdesc, i);
779  /* Fill in the correct relation OID */
780  attr->attrelid = new_rel_oid;
781  /* Make sure this is OK, too */
782  attr->attstattarget = -1;
783 
784  InsertPgAttributeTuple(rel, attr, indstate);
785 
786  /* Add dependency info */
787  myself.classId = RelationRelationId;
788  myself.objectId = new_rel_oid;
789  myself.objectSubId = i + 1;
790  referenced.classId = TypeRelationId;
791  referenced.objectId = attr->atttypid;
792  referenced.objectSubId = 0;
793  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
794 
795  /* The default collation is pinned, so don't bother recording it */
796  if (OidIsValid(attr->attcollation) &&
797  attr->attcollation != DEFAULT_COLLATION_OID)
798  {
799  referenced.classId = CollationRelationId;
800  referenced.objectId = attr->attcollation;
801  referenced.objectSubId = 0;
802  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
803  }
804  }
805 
806  /*
807  * Next we add the system attributes. Skip OID if rel has no OIDs. Skip
808  * all for a view or type relation. We don't bother with making datatype
809  * dependencies here, since presumably all these types are pinned.
810  */
811  if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
812  {
813  for (i = 0; i < (int) lengthof(SysAtt); i++)
814  {
815  FormData_pg_attribute attStruct;
816 
817  memcpy(&attStruct, SysAtt[i], sizeof(FormData_pg_attribute));
818 
819  /* Fill in the correct relation OID in the copied tuple */
820  attStruct.attrelid = new_rel_oid;
821 
822  InsertPgAttributeTuple(rel, &attStruct, indstate);
823  }
824  }
825 
826  /*
827  * clean up
828  */
829  CatalogCloseIndexes(indstate);
830 
832 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
#define lengthof(array)
Definition: c.h:669
#define OidIsValid(objectId)
Definition: c.h:645
char relkind
Definition: pg_class.h:81
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
FormData_pg_attribute
Definition: pg_attribute.h:184
static const FormData_pg_attribute * SysAtt[]
Definition: heap.c:242
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:42
void InsertPgAttributeTuple(Relation pg_attribute_rel, Form_pg_attribute new_attribute, CatalogIndexState indstate)
Definition: heap.c:694
int i
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:60
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ AddNewRelationTuple()

static void AddNewRelationTuple ( Relation  pg_class_desc,
Relation  new_rel_desc,
Oid  new_rel_oid,
Oid  new_type_oid,
Oid  reloftype,
Oid  relowner,
char  relkind,
TransactionId  relfrozenxid,
TransactionId  relminmxid,
Datum  relacl,
Datum  reloptions 
)
static

Definition at line 921 of file heap.c.

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

Referenced by heap_create_with_catalog().

932 {
933  Form_pg_class new_rel_reltup;
934 
935  /*
936  * first we update some of the information in our uncataloged relation's
937  * relation descriptor.
938  */
939  new_rel_reltup = new_rel_desc->rd_rel;
940 
941  switch (relkind)
942  {
943  case RELKIND_RELATION:
944  case RELKIND_MATVIEW:
945  case RELKIND_INDEX:
946  case RELKIND_TOASTVALUE:
947  /* The relation is real, but as yet empty */
948  new_rel_reltup->relpages = 0;
949  new_rel_reltup->reltuples = 0;
950  new_rel_reltup->relallvisible = 0;
951  break;
952  case RELKIND_SEQUENCE:
953  /* Sequences always have a known size */
954  new_rel_reltup->relpages = 1;
955  new_rel_reltup->reltuples = 1;
956  new_rel_reltup->relallvisible = 0;
957  break;
958  default:
959  /* Views, etc, have no disk storage */
960  new_rel_reltup->relpages = 0;
961  new_rel_reltup->reltuples = 0;
962  new_rel_reltup->relallvisible = 0;
963  break;
964  }
965 
966  new_rel_reltup->relfrozenxid = relfrozenxid;
967  new_rel_reltup->relminmxid = relminmxid;
968  new_rel_reltup->relowner = relowner;
969  new_rel_reltup->reltype = new_type_oid;
970  new_rel_reltup->reloftype = reloftype;
971 
972  /* relispartition is always set by updating this tuple later */
973  new_rel_reltup->relispartition = false;
974 
975  new_rel_desc->rd_att->tdtypeid = new_type_oid;
976 
977  /* Now build and insert the tuple */
978  InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid,
979  relacl, reloptions);
980 }
Form_pg_class rd_rel
Definition: rel.h:83
char relkind
Definition: pg_class.h:81
void InsertPgClassTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
Definition: heap.c:848
TupleDesc rd_att
Definition: rel.h:84
TransactionId relminmxid
Definition: pg_class.h:126
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
Oid tdtypeid
Definition: tupdesc.h:82
TransactionId relfrozenxid
Definition: pg_class.h:123

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

References DEFAULT_TYPDELIM, InvalidOid, and TypeCreate().

Referenced by heap_create_with_catalog().

997 {
998  return
999  TypeCreate(new_row_type, /* optional predetermined OID */
1000  typeName, /* type name */
1001  typeNamespace, /* type namespace */
1002  new_rel_oid, /* relation oid */
1003  new_rel_kind, /* relation kind */
1004  ownerid, /* owner's ID */
1005  -1, /* internal size (varlena) */
1006  TYPTYPE_COMPOSITE, /* type-type (composite) */
1007  TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
1008  false, /* composite types are never preferred */
1009  DEFAULT_TYPDELIM, /* default array delimiter */
1010  F_RECORD_IN, /* input procedure */
1011  F_RECORD_OUT, /* output procedure */
1012  F_RECORD_RECV, /* receive procedure */
1013  F_RECORD_SEND, /* send procedure */
1014  InvalidOid, /* typmodin procedure - none */
1015  InvalidOid, /* typmodout procedure - none */
1016  InvalidOid, /* analyze procedure - default */
1017  InvalidOid, /* array element type - irrelevant */
1018  false, /* this is not an array type */
1019  new_array_type, /* array type if any */
1020  InvalidOid, /* domain base type - irrelevant */
1021  NULL, /* default value - none */
1022  NULL, /* default binary representation */
1023  false, /* passed by reference */
1024  'd', /* alignment - must be the largest! */
1025  'x', /* fully TOASTable */
1026  -1, /* typmod */
1027  0, /* array dimensions for typBaseType */
1028  false, /* Type NOT NULL */
1029  InvalidOid); /* rowtypes never have a collation */
1030 }
#define InvalidOid
Definition: postgres_ext.h:36
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
ObjectAddress TypeCreate(Oid newTypeOid, const char *typeName, Oid typeNamespace, Oid relationOid, char relationKind, Oid ownerId, int16 internalSize, char typeType, char typeCategory, bool typePreferred, char typDelim, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, bool isImplicitArray, Oid arrayType, Oid baseType, const char *defaultTypeValue, char *defaultTypeBin, bool passedByValue, char alignment, char storage, int32 typeMod, int32 typNDims, bool typeNotNull, Oid typeCollation)
Definition: pg_type.c:192

◆ AddRelationNewConstraints()

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

Definition at line 2490 of file heap.c.

References AccessShareLock, addRangeTableEntryForRelation(), addRTEtoQuery(), 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().

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

◆ check_nested_generated()

static void check_nested_generated ( ParseState pstate,
Node node 
)
static

Definition at line 2955 of file heap.c.

References check_nested_generated_walker().

Referenced by cookDefault().

2956 {
2957  check_nested_generated_walker(node, pstate);
2958 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:2924

◆ check_nested_generated_walker()

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

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

2925 {
2926  ParseState *pstate = context;
2927 
2928  if (node == NULL)
2929  return false;
2930  else if (IsA(node, Var))
2931  {
2932  Var *var = (Var *) node;
2933  Oid relid;
2935 
2936  relid = rt_fetch(var->varno, pstate->p_rtable)->relid;
2937  attnum = var->varattno;
2938 
2939  if (OidIsValid(relid) && AttributeNumberIsValid(attnum) && get_attgenerated(relid, attnum))
2940  ereport(ERROR,
2941  (errcode(ERRCODE_SYNTAX_ERROR),
2942  errmsg("cannot use generated column \"%s\" in column generation expression",
2943  get_attname(relid, attnum, false)),
2944  errdetail("A generated column cannot reference another generated column."),
2945  parser_errposition(pstate, var->location)));
2946 
2947  return false;
2948  }
2949  else
2951  (void *) context);
2952 }
static bool check_nested_generated_walker(Node *node, void *context)
Definition: heap.c:2924
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
int errcode(int sqlerrcode)
Definition: elog.c:608
AttrNumber varattno
Definition: primnodes.h:172
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:167
#define OidIsValid(objectId)
Definition: c.h:645
#define ERROR
Definition: elog.h:43
int location
Definition: primnodes.h:182
int errdetail(const char *fmt,...)
Definition: elog.c:955
#define ereport(elevel, rest)
Definition: elog.h:141
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:836
Index varno
Definition: primnodes.h:170
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
int16 attnum
Definition: pg_attribute.h:79
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1839
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
int errmsg(const char *fmt,...)
Definition: elog.c:822
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
int16 AttrNumber
Definition: attnum.h:21
List * p_rtable
Definition: parse_node.h:177

◆ CheckAttributeNamesTypes()

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

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

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

◆ CheckAttributeType()

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

Definition at line 578 of file heap.c.

References AccessShareLock, CheckAttributeType(), CHKATYPE_ANYARRAY, CHKATYPE_ANYRECORD, ereport, errcode(), errhint(), errmsg(), ERROR, format_type_be(), get_element_type(), 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(), and ConstructTupleDescriptor().

582 {
583  char att_typtype = get_typtype(atttypid);
584  Oid att_typelem;
585 
586  if (att_typtype == TYPTYPE_PSEUDO)
587  {
588  /*
589  * We disallow pseudo-type columns, with the exception of ANYARRAY,
590  * RECORD, and RECORD[] when the caller says that those are OK.
591  *
592  * We don't need to worry about recursive containment for RECORD and
593  * RECORD[] because (a) no named composite type should be allowed to
594  * contain those, and (b) two "anonymous" record types couldn't be
595  * considered to be the same type, so infinite recursion isn't
596  * possible.
597  */
598  if (!((atttypid == ANYARRAYOID && (flags & CHKATYPE_ANYARRAY)) ||
599  (atttypid == RECORDOID && (flags & CHKATYPE_ANYRECORD)) ||
600  (atttypid == RECORDARRAYOID && (flags & CHKATYPE_ANYRECORD))))
601  ereport(ERROR,
602  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
603  errmsg("column \"%s\" has pseudo-type %s",
605  }
606  else if (att_typtype == TYPTYPE_DOMAIN)
607  {
608  /*
609  * If it's a domain, recurse to check its base type.
610  */
612  containing_rowtypes,
613  flags);
614  }
615  else if (att_typtype == TYPTYPE_COMPOSITE)
616  {
617  /*
618  * For a composite type, recurse into its attributes.
619  */
620  Relation relation;
621  TupleDesc tupdesc;
622  int i;
623 
624  /*
625  * Check for self-containment. Eventually we might be able to allow
626  * this (just return without complaint, if so) but it's not clear how
627  * many other places would require anti-recursion defenses before it
628  * would be safe to allow tables to contain their own rowtype.
629  */
630  if (list_member_oid(containing_rowtypes, atttypid))
631  ereport(ERROR,
632  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
633  errmsg("composite type %s cannot be made a member of itself",
635 
636  containing_rowtypes = lappend_oid(containing_rowtypes, atttypid);
637 
639 
640  tupdesc = RelationGetDescr(relation);
641 
642  for (i = 0; i < tupdesc->natts; i++)
643  {
644  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
645 
646  if (attr->attisdropped)
647  continue;
648  CheckAttributeType(NameStr(attr->attname),
649  attr->atttypid, attr->attcollation,
650  containing_rowtypes,
651  flags);
652  }
653 
654  relation_close(relation, AccessShareLock);
655 
656  containing_rowtypes = list_delete_last(containing_rowtypes);
657  }
658  else if (OidIsValid((att_typelem = get_element_type(atttypid))))
659  {
660  /*
661  * Must recurse into array types, too, in case they are composite.
662  */
664  containing_rowtypes,
665  flags);
666  }
667 
668  /*
669  * This might not be strictly invalid per SQL standard, but it is pretty
670  * useless, and it cannot be dumped, so we must disallow it.
671  */
673  ereport(ERROR,
674  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
675  errmsg("no collation was derived for column \"%s\" with collatable type %s",
677  errhint("Use the COLLATE clause to set the collation explicitly.")));
678 }
int errhint(const char *fmt,...)
Definition: elog.c:1069
#define RelationGetDescr(relation)
Definition: rel.h:448
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2526
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:608
char get_typtype(Oid typid)
Definition: lsyscache.c:2407
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:358
#define OidIsValid(objectId)
Definition: c.h:645
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2499
#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:164
List * list_delete_last(List *list)
Definition: list.c:878
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
Oid atttypid
Definition: pg_attribute.h:49
#define ereport(elevel, rest)
Definition: elog.h:141
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:675
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:822
int i
#define NameStr(name)
Definition: c.h:616
void CheckAttributeType(const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
Definition: heap.c:578
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2299
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:2848

◆ cookConstraint()

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

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

3051 {
3052  Node *expr;
3053 
3054  /*
3055  * Transform raw parsetree to executable expression.
3056  */
3057  expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
3058 
3059  /*
3060  * Make sure it yields a boolean result.
3061  */
3062  expr = coerce_to_boolean(pstate, expr, "CHECK");
3063 
3064  /*
3065  * Take care of collations.
3066  */
3067  assign_expr_collations(pstate, expr);
3068 
3069  /*
3070  * Make sure no outside relations are referred to (this is probably dead
3071  * code now that add_missing_from is history).
3072  */
3073  if (list_length(pstate->p_rtable) != 1)
3074  ereport(ERROR,
3075  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
3076  errmsg("only table \"%s\" can be referenced in check constraint",
3077  relname)));
3078 
3079  return expr;
3080 }
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:144
Definition: nodes.h:525
int errcode(int sqlerrcode)
Definition: elog.c:608
NameData relname
Definition: pg_class.h:35
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
static int list_length(const List *l)
Definition: pg_list.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:822
List * p_rtable
Definition: parse_node.h:177
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 2973 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().

2979 {
2980  Node *expr;
2981 
2982  Assert(raw_default != NULL);
2983 
2984  /*
2985  * Transform raw parsetree to executable expression.
2986  */
2987  expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
2988 
2989  if (attgenerated)
2990  {
2991  check_nested_generated(pstate, expr);
2992 
2993  if (contain_mutable_functions(expr))
2994  ereport(ERROR,
2995  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2996  errmsg("generation expression is not immutable")));
2997  }
2998  else
2999  {
3000  /*
3001  * For a default expression, transformExpr() should have rejected
3002  * column references.
3003  */
3004  Assert(!contain_var_clause(expr));
3005  }
3006 
3007  /*
3008  * Coerce the expression to the correct type and typmod, if given. This
3009  * should match the parser's processing of non-defaulted expressions ---
3010  * see transformAssignedExpr().
3011  */
3012  if (OidIsValid(atttypid))
3013  {
3014  Oid type_id = exprType(expr);
3015 
3016  expr = coerce_to_target_type(pstate, expr, type_id,
3017  atttypid, atttypmod,
3020  -1);
3021  if (expr == NULL)
3022  ereport(ERROR,
3023  (errcode(ERRCODE_DATATYPE_MISMATCH),
3024  errmsg("column \"%s\" is of type %s"
3025  " but default expression is of type %s",
3026  attname,
3028  format_type_be(type_id)),
3029  errhint("You will need to rewrite or cast the expression.")));
3030  }
3031 
3032  /*
3033  * Finally, take care of collations in the finished expression.
3034  */
3035  assign_expr_collations(pstate, expr);
3036 
3037  return expr;
3038 }
int errhint(const char *fmt,...)
Definition: elog.c:1069
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:144
Definition: nodes.h:525
int errcode(int sqlerrcode)
Definition: elog.c:608
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
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:78
Oid atttypid
Definition: pg_attribute.h:49
#define ereport(elevel, rest)
Definition: elog.h:141
#define Assert(condition)
Definition: c.h:739
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static void check_nested_generated(ParseState *pstate, Node *node)
Definition: heap.c:2955
int errmsg(const char *fmt,...)
Definition: elog.c:822
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:645

◆ DeleteAttributeTuples()

void DeleteAttributeTuples ( Oid  relid)

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

1502 {
1503  Relation attrel;
1504  SysScanDesc scan;
1505  ScanKeyData key[1];
1506  HeapTuple atttup;
1507 
1508  /* Grab an appropriate lock on the pg_attribute relation */
1509  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1510 
1511  /* Use the index to scan only attributes of the target relation */
1512  ScanKeyInit(&key[0],
1513  Anum_pg_attribute_attrelid,
1514  BTEqualStrategyNumber, F_OIDEQ,
1515  ObjectIdGetDatum(relid));
1516 
1517  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1518  NULL, 1, key);
1519 
1520  /* Delete all the matching tuples */
1521  while ((atttup = systable_getnext(scan)) != NULL)
1522  CatalogTupleDelete(attrel, &atttup->t_self);
1523 
1524  /* Clean up after the scan */
1525  systable_endscan(scan);
1526  table_close(attrel, RowExclusiveLock);
1527 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ DeleteRelationTuple()

void DeleteRelationTuple ( Oid  relid)

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

1473 {
1474  Relation pg_class_desc;
1475  HeapTuple tup;
1476 
1477  /* Grab an appropriate lock on the pg_class relation */
1478  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1479 
1480  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1481  if (!HeapTupleIsValid(tup))
1482  elog(ERROR, "cache lookup failed for relation %u", relid);
1483 
1484  /* delete the relation tuple from pg_class, and finish up */
1485  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1486 
1487  ReleaseSysCache(tup);
1488 
1489  table_close(pg_class_desc, RowExclusiveLock);
1490 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

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

1539 {
1540  Relation attrel;
1541  SysScanDesc scan;
1542  ScanKeyData key[2];
1543  HeapTuple atttup;
1544 
1545  /* Grab an appropriate lock on the pg_attribute relation */
1546  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1547 
1548  /* Use the index to scan only system attributes of the target relation */
1549  ScanKeyInit(&key[0],
1550  Anum_pg_attribute_attrelid,
1551  BTEqualStrategyNumber, F_OIDEQ,
1552  ObjectIdGetDatum(relid));
1553  ScanKeyInit(&key[1],
1554  Anum_pg_attribute_attnum,
1555  BTLessEqualStrategyNumber, F_INT2LE,
1556  Int16GetDatum(0));
1557 
1558  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1559  NULL, 2, key);
1560 
1561  /* Delete all the matching tuples */
1562  while ((atttup = systable_getnext(scan)) != NULL)
1563  CatalogTupleDelete(attrel, &atttup->t_self);
1564 
1565  /* Clean up after the scan */
1566  systable_endscan(scan);
1567  table_close(attrel, RowExclusiveLock);
1568 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define Int16GetDatum(X)
Definition: postgres.h:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ heap_create()

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

Definition at line 295 of file heap.c.

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

Referenced by heap_create_with_catalog(), and index_create().

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

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

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

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

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

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

Definition at line 1820 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(), relispartition, 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().

1821 {
1822  Relation rel;
1823  HeapTuple tuple;
1824  Oid parentOid = InvalidOid,
1825  defaultPartOid = InvalidOid;
1826 
1827  /*
1828  * To drop a partition safely, we must grab exclusive lock on its parent,
1829  * because another backend might be about to execute a query on the parent
1830  * table. If it relies on previously cached partition descriptor, then it
1831  * could attempt to access the just-dropped relation as its partition. We
1832  * must therefore take a table lock strong enough to prevent all queries
1833  * on the table from proceeding until we commit and send out a
1834  * shared-cache-inval notice that will make them update their partition
1835  * descriptors.
1836  */
1837  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1838  if (!HeapTupleIsValid(tuple))
1839  elog(ERROR, "cache lookup failed for relation %u", relid);
1840  if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
1841  {
1842  parentOid = get_partition_parent(relid);
1844 
1845  /*
1846  * If this is not the default partition, dropping it will change the
1847  * default partition's partition constraint, so we must lock it.
1848  */
1849  defaultPartOid = get_default_partition_oid(parentOid);
1850  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1851  LockRelationOid(defaultPartOid, AccessExclusiveLock);
1852  }
1853 
1854  ReleaseSysCache(tuple);
1855 
1856  /*
1857  * Open and lock the relation.
1858  */
1859  rel = relation_open(relid, AccessExclusiveLock);
1860 
1861  /*
1862  * There can no longer be anyone *else* touching the relation, but we
1863  * might still have open queries or cursors, or pending trigger events, in
1864  * our own session.
1865  */
1866  CheckTableNotInUse(rel, "DROP TABLE");
1867 
1868  /*
1869  * This effectively deletes all rows in the table, and may be done in a
1870  * serializable transaction. In that case we must record a rw-conflict in
1871  * to this transaction from each transaction holding a predicate lock on
1872  * the table.
1873  */
1875 
1876  /*
1877  * Delete pg_foreign_table tuple first.
1878  */
1879  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1880  {
1881  Relation rel;
1882  HeapTuple tuple;
1883 
1884  rel = table_open(ForeignTableRelationId, RowExclusiveLock);
1885 
1887  if (!HeapTupleIsValid(tuple))
1888  elog(ERROR, "cache lookup failed for foreign table %u", relid);
1889 
1890  CatalogTupleDelete(rel, &tuple->t_self);
1891 
1892  ReleaseSysCache(tuple);
1894  }
1895 
1896  /*
1897  * If a partitioned table, delete the pg_partitioned_table tuple.
1898  */
1899  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1901 
1902  /*
1903  * If the relation being dropped is the default partition itself,
1904  * invalidate its entry in pg_partitioned_table.
1905  */
1906  if (relid == defaultPartOid)
1908 
1909  /*
1910  * Schedule unlinking of the relation's physical files at commit.
1911  */
1912  if (rel->rd_rel->relkind != RELKIND_VIEW &&
1913  rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
1914  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1915  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1916  {
1917  RelationDropStorage(rel);
1918  }
1919 
1920  /*
1921  * Close relcache entry, but *keep* AccessExclusiveLock on the relation
1922  * until transaction commit. This ensures no one else will try to do
1923  * something with the doomed relation.
1924  */
1925  relation_close(rel, NoLock);
1926 
1927  /*
1928  * Remove any associated relation synchronization states.
1929  */
1931 
1932  /*
1933  * Forget any ON COMMIT action for the rel
1934  */
1935  remove_on_commit_action(relid);
1936 
1937  /*
1938  * Flush the relation from the relcache. We want to do this before
1939  * starting to remove catalog entries, just to be certain that no relcache
1940  * entry rebuild will happen partway through. (That should not really
1941  * matter, since we don't do CommandCounterIncrement here, but let's be
1942  * safe.)
1943  */
1944  RelationForgetRelation(relid);
1945 
1946  /*
1947  * remove inheritance information
1948  */
1950 
1951  /*
1952  * delete statistics
1953  */
1954  RemoveStatistics(relid, 0);
1955 
1956  /*
1957  * delete attribute tuples
1958  */
1959  DeleteAttributeTuples(relid);
1960 
1961  /*
1962  * delete relation tuple
1963  */
1964  DeleteRelationTuple(relid);
1965 
1966  if (OidIsValid(parentOid))
1967  {
1968  /*
1969  * If this is not the default partition, the partition constraint of
1970  * the default partition has changed to include the portion of the key
1971  * space previously covered by the dropped partition.
1972  */
1973  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1974  CacheInvalidateRelcacheByRelid(defaultPartOid);
1975 
1976  /*
1977  * Invalidate the parent's relcache so that the partition is no longer
1978  * included in its partition descriptor.
1979  */
1980  CacheInvalidateRelcacheByRelid(parentOid);
1981  /* keep the lock */
1982  }
1983 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void RemoveSubscriptionRel(Oid subid, Oid relid)
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:323
void remove_on_commit_action(Oid relid)
Definition: tablecmds.c:14566
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2702
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
Form_pg_class rd_rel
Definition: rel.h:83
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
Oid get_partition_parent(Oid relid)
Definition: partition.c:50
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1329
bool relispartition
Definition: pg_class.h:117
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3421
Oid get_default_partition_oid(Oid parentId)
Definition: partition.c:298
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void RelationDropStorage(Relation rel)
Definition: storage.c:147
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define InvalidOid
Definition: postgres_ext.h:36
void DeleteRelationTuple(Oid relid)
Definition: heap.c:1472
#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:1439
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4510
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1501
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:3090
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
#define AccessExclusiveLock
Definition: lockdefs.h:45
void RemovePartitionKeyByRelId(Oid relid)
Definition: heap.c:3545
#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 3185 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().

3186 {
3187  List *relations = NIL;
3188  ListCell *cell;
3189 
3190  /* Open relations for processing, and grab exclusive access on each */
3191  foreach(cell, relids)
3192  {
3193  Oid rid = lfirst_oid(cell);
3194  Relation rel;
3195 
3196  rel = table_open(rid, AccessExclusiveLock);
3197  relations = lappend(relations, rel);
3198  }
3199 
3200  /* Don't allow truncate on tables that are referenced by foreign keys */
3201  heap_truncate_check_FKs(relations, true);
3202 
3203  /* OK to do it */
3204  foreach(cell, relations)
3205  {
3206  Relation rel = lfirst(cell);
3207 
3208  /* Truncate the relation */
3209  heap_truncate_one_rel(rel);
3210 
3211  /* Close the relation, but keep exclusive lock on it until commit */
3212  table_close(rel, NoLock);
3213  }
3214 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:3226
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3270
unsigned int Oid
Definition: postgres_ext.h:31
#define NoLock
Definition: lockdefs.h:34
List * lappend(List *list, void *datum)
Definition: list.c:322
#define lfirst(lc)
Definition: pg_list.h:190
#define AccessExclusiveLock
Definition: lockdefs.h:45
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ heap_truncate_check_FKs()

void heap_truncate_check_FKs ( List relations,
bool  tempTables 
)

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

3271 {
3272  List *oids = NIL;
3273  List *dependents;
3274  ListCell *cell;
3275 
3276  /*
3277  * Build a list of OIDs of the interesting relations.
3278  *
3279  * If a relation has no triggers, then it can neither have FKs nor be
3280  * referenced by a FK from another table, so we can ignore it. For
3281  * partitioned tables, FKs have no triggers, so we must include them
3282  * anyway.
3283  */
3284  foreach(cell, relations)
3285  {
3286  Relation rel = lfirst(cell);
3287 
3288  if (rel->rd_rel->relhastriggers ||
3289  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3290  oids = lappend_oid(oids, RelationGetRelid(rel));
3291  }
3292 
3293  /*
3294  * Fast path: if no relation has triggers, none has FKs either.
3295  */
3296  if (oids == NIL)
3297  return;
3298 
3299  /*
3300  * Otherwise, must scan pg_constraint. We make one pass with all the
3301  * relations considered; if this finds nothing, then all is well.
3302  */
3303  dependents = heap_truncate_find_FKs(oids);
3304  if (dependents == NIL)
3305  return;
3306 
3307  /*
3308  * Otherwise we repeat the scan once per relation to identify a particular
3309  * pair of relations to complain about. This is pretty slow, but
3310  * performance shouldn't matter much in a failure path. The reason for
3311  * doing things this way is to ensure that the message produced is not
3312  * dependent on chance row locations within pg_constraint.
3313  */
3314  foreach(cell, oids)
3315  {
3316  Oid relid = lfirst_oid(cell);
3317  ListCell *cell2;
3318 
3319  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
3320 
3321  foreach(cell2, dependents)
3322  {
3323  Oid relid2 = lfirst_oid(cell2);
3324 
3325  if (!list_member_oid(oids, relid2))
3326  {
3327  char *relname = get_rel_name(relid);
3328  char *relname2 = get_rel_name(relid2);
3329 
3330  if (tempTables)
3331  ereport(ERROR,
3332  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3333  errmsg("unsupported ON COMMIT and foreign key combination"),
3334  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3335  relname2, relname)));
3336  else
3337  ereport(ERROR,
3338  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3339  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3340  errdetail("Table \"%s\" references \"%s\".",
3341  relname2, relname),
3342  errhint("Truncate table \"%s\" at the same time, "
3343  "or use TRUNCATE ... CASCADE.",
3344  relname2)));
3345  }
3346  }
3347  }
3348 }
#define NIL
Definition: pg_list.h:65
int errhint(const char *fmt,...)
Definition: elog.c:1069
int errcode(int sqlerrcode)
Definition: elog.c:608
Form_pg_class rd_rel
Definition: rel.h:83
NameData relname
Definition: pg_class.h:35
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:358
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:955
#define ereport(elevel, rest)
Definition: elog.h:141
#define list_make1_oid(x1)
Definition: pg_list.h:249
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:675
#define lfirst(lc)
Definition: pg_list.h:190
int errmsg(const char *fmt,...)
Definition: elog.c:822
Definition: pg_list.h:50
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730
#define RelationGetRelid(relation)
Definition: rel.h:422
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3365
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

Definition at line 3365 of file heap.c.

References AccessShareLock, GETSTRUCT, HeapTupleIsValid, InvalidOid, lappend_oid(), list_deduplicate_oid(), list_member_oid(), list_oid_cmp(), list_sort(), NIL, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ExecuteTruncateGuts(), and heap_truncate_check_FKs().

3366 {
3367  List *result = NIL;
3368  Relation fkeyRel;
3369  SysScanDesc fkeyScan;
3370  HeapTuple tuple;
3371 
3372  /*
3373  * Must scan pg_constraint. Right now, it is a seqscan because there is
3374  * no available index on confrelid.
3375  */
3376  fkeyRel = table_open(ConstraintRelationId, AccessShareLock);
3377 
3378  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3379  NULL, 0, NULL);
3380 
3381  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3382  {
3384 
3385  /* Not a foreign key */
3386  if (con->contype != CONSTRAINT_FOREIGN)
3387  continue;
3388 
3389  /* Not referencing one of our list of tables */
3390  if (!list_member_oid(relationIds, con->confrelid))
3391  continue;
3392 
3393  /* Add referencer to result, unless present in input list */
3394  if (!list_member_oid(relationIds, con->conrelid))
3395  result = lappend_oid(result, con->conrelid);
3396  }
3397 
3398  systable_endscan(fkeyScan);
3399  table_close(fkeyRel, AccessShareLock);
3400 
3401  /* Now sort and de-duplicate the result list */
3402  list_sort(result, list_oid_cmp);
3403  list_deduplicate_oid(result);
3404 
3405  return result;
3406 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define AccessShareLock
Definition: lockdefs.h:36
List * lappend_oid(List *list, Oid datum)
Definition: list.c:358
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1499
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
void list_deduplicate_oid(List *list)
Definition: list.c:1326
#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:675
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1482
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50

◆ heap_truncate_one_rel()

void heap_truncate_one_rel ( Relation  rel)

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

3227 {
3228  Oid toastrelid;
3229 
3230  /*
3231  * Truncate the relation. Partitioned tables have no storage, so there is
3232  * nothing to do for them here.
3233  */
3234  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3235  return;
3236 
3237  /* Truncate the underlying relation */
3239 
3240  /* If the relation has indexes, truncate the indexes too */
3242 
3243  /* If there is a toast table, truncate that too */
3244  toastrelid = rel->rd_rel->reltoastrelid;
3245  if (OidIsValid(toastrelid))
3246  {
3247  Relation toastrel = table_open(toastrelid, AccessExclusiveLock);
3248 
3250  RelationTruncateIndexes(toastrel);
3251  /* keep the lock... */
3252  table_close(toastrel, NoLock);
3253  }
3254 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
Form_pg_class rd_rel
Definition: rel.h:83
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
static void table_relation_nontransactional_truncate(Relation rel)
Definition: tableam.h:1361
#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:3137

◆ InsertPgAttributeTuple()

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

Definition at line 694 of file heap.c.

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

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

697 {
698  Datum values[Natts_pg_attribute];
699  bool nulls[Natts_pg_attribute];
700  HeapTuple tup;
701 
702  /* This is a tad tedious, but way cleaner than what we used to do... */
703  memset(values, 0, sizeof(values));
704  memset(nulls, false, sizeof(nulls));
705 
706  values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
707  values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
708  values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
709  values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
710  values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
711  values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
712  values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
713  values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
714  values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
715  values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
716  values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
717  values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
718  values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
719  values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
720  values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(new_attribute->atthasmissing);
721  values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
722  values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(new_attribute->attgenerated);
723  values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
724  values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
725  values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
726  values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
727 
728  /* start out with empty permissions and empty options */
729  nulls[Anum_pg_attribute_attacl - 1] = true;
730  nulls[Anum_pg_attribute_attoptions - 1] = true;
731  nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
732  nulls[Anum_pg_attribute_attmissingval - 1] = true;
733 
734  tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
735 
736  /* finally insert the new tuple, update the indexes, and clean up */
737  if (indstate != NULL)
738  CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
739  else
740  CatalogTupleInsert(pg_attribute_rel, tup);
741 
742  heap_freetuple(tup);
743 }
#define NameGetDatum(X)
Definition: postgres.h:595
#define RelationGetDescr(relation)
Definition: rel.h:448
#define Int16GetDatum(X)
Definition: postgres.h:451
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
uintptr_t Datum
Definition: postgres.h:367
void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:204
#define BoolGetDatum(X)
Definition: postgres.h:402
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define Int32GetDatum(X)
Definition: postgres.h:479
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ InsertPgClassTuple()

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

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

853 {
854  Form_pg_class rd_rel = new_rel_desc->rd_rel;
855  Datum values[Natts_pg_class];
856  bool nulls[Natts_pg_class];
857  HeapTuple tup;
858 
859  /* This is a tad tedious, but way cleaner than what we used to do... */
860  memset(values, 0, sizeof(values));
861  memset(nulls, false, sizeof(nulls));
862 
863  values[Anum_pg_class_oid - 1] = ObjectIdGetDatum(new_rel_oid);
864  values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
865  values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
866  values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
867  values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
868  values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
869  values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
870  values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
871  values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
872  values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
873  values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
874  values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
875  values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
876  values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
877  values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
878  values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
879  values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
880  values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
881  values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
882  values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
883  values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
884  values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
885  values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
886  values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
887  values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
888  values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
889  values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
890  values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite);
891  values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
892  values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
893  if (relacl != (Datum) 0)
894  values[Anum_pg_class_relacl - 1] = relacl;
895  else
896  nulls[Anum_pg_class_relacl - 1] = true;
897  if (reloptions != (Datum) 0)
898  values[Anum_pg_class_reloptions - 1] = reloptions;
899  else
900  nulls[Anum_pg_class_reloptions - 1] = true;
901 
902  /* relpartbound is set by updating this tuple, if necessary */
903  nulls[Anum_pg_class_relpartbound - 1] = true;
904 
905  tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
906 
907  /* finally insert the new tuple, update the indexes, and clean up */
908  CatalogTupleInsert(pg_class_desc, tup);
909 
910  heap_freetuple(tup);
911 }
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:448
#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:83
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define TransactionIdGetDatum(X)
Definition: postgres.h:521
uintptr_t Datum
Definition: postgres.h:367
#define BoolGetDatum(X)
Definition: postgres.h:402
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
#define Int32GetDatum(X)
Definition: postgres.h:479
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ MergeWithExistingConstraint()

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

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

2744 {
2745  bool found;
2746  Relation conDesc;
2747  SysScanDesc conscan;
2748  ScanKeyData skey[3];
2749  HeapTuple tup;
2750 
2751  /* Search for a pg_constraint entry with same name and relation */
2752  conDesc = table_open(ConstraintRelationId, RowExclusiveLock);
2753 
2754  found = false;
2755 
2756  ScanKeyInit(&skey[0],
2757  Anum_pg_constraint_conrelid,
2758  BTEqualStrategyNumber, F_OIDEQ,
2760  ScanKeyInit(&skey[1],
2761  Anum_pg_constraint_contypid,
2762  BTEqualStrategyNumber, F_OIDEQ,
2764  ScanKeyInit(&skey[2],
2765  Anum_pg_constraint_conname,
2766  BTEqualStrategyNumber, F_NAMEEQ,
2767  CStringGetDatum(ccname));
2768 
2769  conscan = systable_beginscan(conDesc, ConstraintRelidTypidNameIndexId, true,
2770  NULL, 3, skey);
2771 
2772  /* There can be at most one matching row */
2773  if (HeapTupleIsValid(tup = systable_getnext(conscan)))
2774  {
2776 
2777  /* Found it. Conflicts if not identical check constraint */
2778  if (con->contype == CONSTRAINT_CHECK)
2779  {
2780  Datum val;
2781  bool isnull;
2782 
2783  val = fastgetattr(tup,
2784  Anum_pg_constraint_conbin,
2785  conDesc->rd_att, &isnull);
2786  if (isnull)
2787  elog(ERROR, "null conbin for rel %s",
2789  if (equal(expr, stringToNode(TextDatumGetCString(val))))
2790  found = true;
2791  }
2792 
2793  /*
2794  * If the existing constraint is purely inherited (no local
2795  * definition) then interpret addition of a local constraint as a
2796  * legal merge. This allows ALTER ADD CONSTRAINT on parent and child
2797  * tables to be given in either order with same end state. However if
2798  * the relation is a partition, all inherited constraints are always
2799  * non-local, including those that were merged.
2800  */
2801  if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
2802  allow_merge = true;
2803 
2804  if (!found || !allow_merge)
2805  ereport(ERROR,
2807  errmsg("constraint \"%s\" for relation \"%s\" already exists",
2808  ccname, RelationGetRelationName(rel))));
2809 
2810  /* If the child constraint is "no inherit" then cannot merge */
2811  if (con->connoinherit)
2812  ereport(ERROR,
2813  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2814  errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
2815  ccname, RelationGetRelationName(rel))));
2816 
2817  /*
2818  * Must not change an existing inherited constraint to "no inherit"
2819  * status. That's because inherited constraints should be able to
2820  * propagate to lower-level children.
2821  */
2822  if (con->coninhcount > 0 && is_no_inherit)
2823  ereport(ERROR,
2824  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2825  errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
2826  ccname, RelationGetRelationName(rel))));
2827 
2828  /*
2829  * If the child constraint is "not valid" then cannot merge with a
2830  * valid parent constraint.
2831  */
2832  if (is_initially_valid && !con->convalidated)
2833  ereport(ERROR,
2834  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2835  errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
2836  ccname, RelationGetRelationName(rel))));
2837 
2838  /* OK to update the tuple */
2839  ereport(NOTICE,
2840  (errmsg("merging constraint \"%s\" with inherited definition",
2841  ccname)));
2842 
2843  tup = heap_copytuple(tup);
2844  con = (Form_pg_constraint) GETSTRUCT(tup);
2845 
2846  /*
2847  * In case of partitions, an inherited constraint must be inherited
2848  * only once since it cannot have multiple parents and it is never
2849  * considered local.
2850  */
2851  if (rel->rd_rel->relispartition)
2852  {
2853  con->coninhcount = 1;
2854  con->conislocal = false;
2855  }
2856  else
2857  {
2858  if (is_local)
2859  con->conislocal = true;
2860  else
2861  con->coninhcount++;
2862  }
2863 
2864  if (is_no_inherit)
2865  {
2866  Assert(is_local);
2867  con->connoinherit = true;
2868  }
2869 
2870  CatalogTupleUpdate(conDesc, &tup->t_self, tup);
2871  }
2872 
2873  systable_endscan(conscan);
2874  table_close(conDesc, RowExclusiveLock);
2875 
2876  return found;
2877 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#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:3011
int errcode(int sqlerrcode)
Definition: elog.c:608
void * stringToNode(const char *str)
Definition: read.c:89
Form_pg_class rd_rel
Definition: rel.h:83
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
#define RelationGetRelationName(relation)
Definition: rel.h:456
#define ereport(elevel, rest)
Definition: elog.h:141
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:84
#define InvalidOid
Definition: postgres_ext.h:36
#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:739
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define ConstraintRelidTypidNameIndexId
Definition: indexing.h:128
int errmsg(const char *fmt,...)
Definition: elog.c:822
#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:31
#define RelationGetRelid(relation)
Definition: rel.h:422
long val
Definition: informix.c:664
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RelationClearMissing()

void RelationClearMissing ( Relation  rel)

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

1998 {
1999  Relation attr_rel;
2000  Oid relid = RelationGetRelid(rel);
2001  int natts = RelationGetNumberOfAttributes(rel);
2002  int attnum;
2003  Datum repl_val[Natts_pg_attribute];
2004  bool repl_null[Natts_pg_attribute];
2005  bool repl_repl[Natts_pg_attribute];
2006  Form_pg_attribute attrtuple;
2007  HeapTuple tuple,
2008  newtuple;
2009 
2010  memset(repl_val, 0, sizeof(repl_val));
2011  memset(repl_null, false, sizeof(repl_null));
2012  memset(repl_repl, false, sizeof(repl_repl));
2013 
2014  repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
2015  repl_null[Anum_pg_attribute_attmissingval - 1] = true;
2016 
2017  repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
2018  repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
2019 
2020 
2021  /* Get a lock on pg_attribute */
2022  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
2023 
2024  /* process each non-system attribute, including any dropped columns */
2025  for (attnum = 1; attnum <= natts; attnum++)
2026  {
2027  tuple = SearchSysCache2(ATTNUM,
2028  ObjectIdGetDatum(relid),
2029  Int16GetDatum(attnum));
2030  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
2031  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2032  attnum, relid);
2033 
2034  attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
2035 
2036  /* ignore any where atthasmissing is not true */
2037  if (attrtuple->atthasmissing)
2038  {
2039  newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
2040  repl_val, repl_null, repl_repl);
2041 
2042  CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
2043 
2044  heap_freetuple(newtuple);
2045  }
2046 
2047  ReleaseSysCache(tuple);
2048  }
2049 
2050  /*
2051  * Our update of the pg_attribute rows will force a relcache rebuild, so
2052  * there's nothing else to do here.
2053  */
2054  table_close(attr_rel, RowExclusiveLock);
2055 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:448
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:428
#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:200
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define BoolGetDatum(X)
Definition: postgres.h:402
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1127
#define elog(elevel,...)
Definition: elog.h: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:422

◆ RelationRemoveInheritance()

static void RelationRemoveInheritance ( Oid  relid)
static

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

1440 {
1441  Relation catalogRelation;
1442  SysScanDesc scan;
1443  ScanKeyData key;
1444  HeapTuple tuple;
1445 
1446  catalogRelation = table_open(InheritsRelationId, RowExclusiveLock);
1447 
1448  ScanKeyInit(&key,
1449  Anum_pg_inherits_inhrelid,
1450  BTEqualStrategyNumber, F_OIDEQ,
1451  ObjectIdGetDatum(relid));
1452 
1453  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
1454  NULL, 1, &key);
1455 
1456  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1457  CatalogTupleDelete(catalogRelation, &tuple->t_self);
1458 
1459  systable_endscan(scan);
1460  table_close(catalogRelation, RowExclusiveLock);
1461 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define InheritsRelidSeqnoIndexId
Definition: indexing.h:171
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RelationTruncateIndexes()

static void RelationTruncateIndexes ( Relation  heapRelation)
static

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

3138 {
3139  ListCell *indlist;
3140 
3141  /* Ask the relcache to produce a list of the indexes of the rel */
3142  foreach(indlist, RelationGetIndexList(heapRelation))
3143  {
3144  Oid indexId = lfirst_oid(indlist);
3145  Relation currentIndex;
3146  IndexInfo *indexInfo;
3147 
3148  /* Open the index relation; use exclusive lock, just to be sure */
3149  currentIndex = index_open(indexId, AccessExclusiveLock);
3150 
3151  /*
3152  * Fetch info needed for index_build. Since we know there are no
3153  * tuples that actually need indexing, we can use a dummy IndexInfo.
3154  * This is slightly cheaper to build, but the real point is to avoid
3155  * possibly running user-defined code in index expressions or
3156  * predicates. We might be getting invoked during ON COMMIT
3157  * processing, and we don't want to run any such code then.
3158  */
3159  indexInfo = BuildDummyIndexInfo(currentIndex);
3160 
3161  /*
3162  * Now truncate the actual file (and discard buffers).
3163  */
3164  RelationTruncate(currentIndex, 0);
3165 
3166  /* Initialize the index and rebuild */
3167  /* Note: we do not need to re-establish pkey setting */
3168  index_build(heapRelation, currentIndex, indexInfo, true, false);
3169 
3170  /* We're done with this index */
3171  index_close(currentIndex, NoLock);
3172  }
3173 }
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:2794
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4347
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:152
#define AccessExclusiveLock
Definition: lockdefs.h:45
IndexInfo * BuildDummyIndexInfo(Relation index)
Definition: index.c:2342
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:126
#define lfirst_oid(lc)
Definition: pg_list.h:192
void RelationTruncate(Relation rel, BlockNumber nblocks)
Definition: storage.c:229

◆ RemoveAttrDefault()

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

Definition at line 1692 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(), and ATExecColumnDefault().

1694 {
1695  Relation attrdef_rel;
1696  ScanKeyData scankeys[2];
1697  SysScanDesc scan;
1698  HeapTuple tuple;
1699  bool found = false;
1700 
1701  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1702 
1703  ScanKeyInit(&scankeys[0],
1704  Anum_pg_attrdef_adrelid,
1705  BTEqualStrategyNumber, F_OIDEQ,
1706  ObjectIdGetDatum(relid));
1707  ScanKeyInit(&scankeys[1],
1708  Anum_pg_attrdef_adnum,
1709  BTEqualStrategyNumber, F_INT2EQ,
1711 
1712  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1713  NULL, 2, scankeys);
1714 
1715  /* There should be at most one matching tuple, but we loop anyway */
1716  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1717  {
1718  ObjectAddress object;
1719  Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
1720 
1721  object.classId = AttrDefaultRelationId;
1722  object.objectId = attrtuple->oid;
1723  object.objectSubId = 0;
1724 
1725  performDeletion(&object, behavior,
1726  internal ? PERFORM_DELETION_INTERNAL : 0);
1727 
1728  found = true;
1729  }
1730 
1731  systable_endscan(scan);
1732  table_close(attrdef_rel, RowExclusiveLock);
1733 
1734  if (complain && !found)
1735  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1736  relid, attnum);
1737 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define Int16GetDatum(X)
Definition: postgres.h:451
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define AttrDefaultIndexId
Definition: indexing.h:89
#define RowExclusiveLock
Definition: lockdefs.h:38
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:315
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 1747 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().

1748 {
1749  Relation attrdef_rel;
1750  Relation attr_rel;
1751  Relation myrel;
1752  ScanKeyData scankeys[1];
1753  SysScanDesc scan;
1754  HeapTuple tuple;
1755  Oid myrelid;
1756  AttrNumber myattnum;
1757 
1758  /* Grab an appropriate lock on the pg_attrdef relation */
1759  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1760 
1761  /* Find the pg_attrdef tuple */
1762  ScanKeyInit(&scankeys[0],
1763  Anum_pg_attrdef_oid,
1764  BTEqualStrategyNumber, F_OIDEQ,
1765  ObjectIdGetDatum(attrdefId));
1766 
1767  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1768  NULL, 1, scankeys);
1769 
1770  tuple = systable_getnext(scan);
1771  if (!HeapTupleIsValid(tuple))
1772  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1773 
1774  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1775  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1776 
1777  /* Get an exclusive lock on the relation owning the attribute */
1778  myrel = relation_open(myrelid, AccessExclusiveLock);
1779 
1780  /* Now we can delete the pg_attrdef row */
1781  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1782 
1783  systable_endscan(scan);
1784  table_close(attrdef_rel, RowExclusiveLock);
1785 
1786  /* Fix the pg_attribute row */
1787  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1788 
1789  tuple = SearchSysCacheCopy2(ATTNUM,
1790  ObjectIdGetDatum(myrelid),
1791  Int16GetDatum(myattnum));
1792  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1793  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1794  myattnum, myrelid);
1795 
1796  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1797 
1798  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1799 
1800  /*
1801  * Our update of the pg_attribute row will force a relcache rebuild, so
1802  * there's nothing else to do here.
1803  */
1804  table_close(attr_rel, RowExclusiveLock);
1805 
1806  /* Keep lock on attribute's rel until end of xact */
1807  relation_close(myrel, NoLock);
1808 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define Int16GetDatum(X)
Definition: postgres.h:451
#define AttrDefaultOidIndexId
Definition: indexing.h:91
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#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:200
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define elog(elevel,...)
Definition: elog.h: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 1579 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().

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

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

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

3546 {
3547  Relation rel;
3548  HeapTuple tuple;
3549 
3550  rel = table_open(PartitionedRelationId, RowExclusiveLock);
3551 
3552  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3553  if (!HeapTupleIsValid(tuple))
3554  elog(ERROR, "cache lookup failed for partition key of relation %u",
3555  relid);
3556 
3557  CatalogTupleDelete(rel, &tuple->t_self);
3558 
3559  ReleaseSysCache(tuple);
3561 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

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

3091 {
3092  Relation pgstatistic;
3093  SysScanDesc scan;
3094  ScanKeyData key[2];
3095  int nkeys;
3096  HeapTuple tuple;
3097 
3098  pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
3099 
3100  ScanKeyInit(&key[0],
3101  Anum_pg_statistic_starelid,
3102  BTEqualStrategyNumber, F_OIDEQ,
3103  ObjectIdGetDatum(relid));
3104 
3105  if (attnum == 0)
3106  nkeys = 1;
3107  else
3108  {
3109  ScanKeyInit(&key[1],
3110  Anum_pg_statistic_staattnum,
3111  BTEqualStrategyNumber, F_INT2EQ,
3113  nkeys = 2;
3114  }
3115 
3116  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
3117  NULL, nkeys, key);
3118 
3119  /* we must loop even when attnum != 0, in case of inherited stats */
3120  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3121  CatalogTupleDelete(pgstatistic, &tuple->t_self);
3122 
3123  systable_endscan(scan);
3124 
3125  table_close(pgstatistic, RowExclusiveLock);
3126 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define Int16GetDatum(X)
Definition: postgres.h:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define StatisticRelidAttnumInhIndexId
Definition: indexing.h:231
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 2065 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().

2066 {
2067  Datum valuesAtt[Natts_pg_attribute];
2068  bool nullsAtt[Natts_pg_attribute];
2069  bool replacesAtt[Natts_pg_attribute];
2070  Datum missingval;
2071  Form_pg_attribute attStruct;
2072  Relation attrrel,
2073  tablerel;
2074  HeapTuple atttup,
2075  newtup;
2076 
2077  /* lock the table the attribute belongs to */
2078  tablerel = table_open(relid, AccessExclusiveLock);
2079 
2080  /* Lock the attribute row and get the data */
2081  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2082  atttup = SearchSysCacheAttName(relid, attname);
2083  if (!HeapTupleIsValid(atttup))
2084  elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2085  attname, relid);
2086  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2087 
2088  /* get an array value from the value string */
2089  missingval = OidFunctionCall3(F_ARRAY_IN,
2091  ObjectIdGetDatum(attStruct->atttypid),
2092  Int32GetDatum(attStruct->atttypmod));
2093 
2094  /* update the tuple - set atthasmissing and attmissingval */
2095  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2096  MemSet(nullsAtt, false, sizeof(nullsAtt));
2097  MemSet(replacesAtt, false, sizeof(replacesAtt));
2098 
2099  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
2100  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2101  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2102  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2103 
2104  newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2105  valuesAtt, nullsAtt, replacesAtt);
2106  CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
2107 
2108  /* clean up */
2109  ReleaseSysCache(atttup);
2110  table_close(attrrel, RowExclusiveLock);
2111  table_close(tablerel, AccessExclusiveLock);
2112 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:448
static struct @145 value
#define MemSet(start, val, len)
Definition: c.h:962
#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:200
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition: fmgr.h:657
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define BoolGetDatum(X)
Definition: postgres.h:402
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1257
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define Int32GetDatum(X)
Definition: postgres.h:479
#define elog(elevel,...)
Definition: elog.h: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 2890 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().

2891 {
2892  Relation relrel;
2893  HeapTuple reltup;
2894  Form_pg_class relStruct;
2895 
2896  relrel = table_open(RelationRelationId, RowExclusiveLock);
2897  reltup = SearchSysCacheCopy1(RELOID,
2899  if (!HeapTupleIsValid(reltup))
2900  elog(ERROR, "cache lookup failed for relation %u",
2901  RelationGetRelid(rel));
2902  relStruct = (Form_pg_class) GETSTRUCT(reltup);
2903 
2904  if (relStruct->relchecks != numchecks)
2905  {
2906  relStruct->relchecks = numchecks;
2907 
2908  CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
2909  }
2910  else
2911  {
2912  /* Skip the disk update, but force relcache inval anyway */
2914  }
2915 
2916  heap_freetuple(reltup);
2917  table_close(relrel, RowExclusiveLock);
2918 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
#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:422

◆ StoreAttrDefault()

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

Definition at line 2126 of file heap.c.

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

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

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

◆ StoreConstraints()

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

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

2421 {
2422  int numchecks = 0;
2423  ListCell *lc;
2424 
2425  if (cooked_constraints == NIL)
2426  return; /* nothing to do */
2427 
2428  /*
2429  * Deparsing of constraint expressions will fail unless the just-created
2430  * pg_attribute tuples for this relation are made visible. So, bump the
2431  * command counter. CAUTION: this will cause a relcache entry rebuild.
2432  */
2434 
2435  foreach(lc, cooked_constraints)
2436  {
2437  CookedConstraint *con = (CookedConstraint *) lfirst(lc);
2438 
2439  switch (con->contype)
2440  {
2441  case CONSTR_DEFAULT:
2442  con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
2443  is_internal, false);
2444  break;
2445  case CONSTR_CHECK:
2446  con->conoid =
2447  StoreRelCheck(rel, con->name, con->expr,
2448  !con->skip_validation, con->is_local,
2449  con->inhcount, con->is_no_inherit,
2450  is_internal);
2451  numchecks++;
2452  break;
2453  default:
2454  elog(ERROR, "unrecognized constraint type: %d",
2455  (int) con->contype);
2456  }
2457  }
2458 
2459  if (numchecks > 0)
2460  SetRelationNumChecks(rel, numchecks);
2461 }
#define NIL
Definition: pg_list.h:65
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2890
bool is_no_inherit
Definition: heap.h:44
AttrNumber attnum
Definition: heap.h:39
#define ERROR
Definition: elog.h:43
int inhcount
Definition: heap.h:43
bool skip_validation
Definition: heap.h:41
ConstrType contype
Definition: heap.h:36
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal, bool add_column_mode)
Definition: heap.c:2126
void CommandCounterIncrement(void)
Definition: xact.c:1005
#define lfirst(lc)
Definition: pg_list.h:190
#define elog(elevel,...)
Definition: elog.h:228
Oid conoid
Definition: heap.h:37
Node * expr
Definition: heap.h:40
char * name
Definition: heap.h:38
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:2312
bool is_local
Definition: heap.h:42

◆ StorePartitionBound()

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

Definition at line 3576 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, relispartition, RELOID, RowExclusiveLock, SearchSysCacheCopy1, SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), and update_default_partition_oid().

Referenced by ATExecAttachPartition(), and DefineRelation().

3577 {
3578  Relation classRel;
3579  HeapTuple tuple,
3580  newtuple;
3581  Datum new_val[Natts_pg_class];
3582  bool new_null[Natts_pg_class],
3583  new_repl[Natts_pg_class];
3584  Oid defaultPartOid;
3585 
3586  /* Update pg_class tuple */
3587  classRel = table_open(RelationRelationId, RowExclusiveLock);
3588  tuple = SearchSysCacheCopy1(RELOID,
3590  if (!HeapTupleIsValid(tuple))
3591  elog(ERROR, "cache lookup failed for relation %u",
3592  RelationGetRelid(rel));
3593 
3594 #ifdef USE_ASSERT_CHECKING
3595  {
3596  Form_pg_class classForm;
3597  bool isnull;
3598 
3599  classForm = (Form_pg_class) GETSTRUCT(tuple);
3600  Assert(!classForm->relispartition);
3601  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3602  &isnull);
3603  Assert(isnull);
3604  }
3605 #endif
3606 
3607  /* Fill in relpartbound value */
3608  memset(new_val, 0, sizeof(new_val));
3609  memset(new_null, false, sizeof(new_null));
3610  memset(new_repl, false, sizeof(new_repl));
3611  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3612  new_null[Anum_pg_class_relpartbound - 1] = false;
3613  new_repl[Anum_pg_class_relpartbound - 1] = true;
3614  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3615  new_val, new_null, new_repl);
3616  /* Also set the flag */
3617  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3618  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3619  heap_freetuple(newtuple);
3620  table_close(classRel, RowExclusiveLock);
3621 
3622  /*
3623  * If we're storing bounds for the default partition, update
3624  * pg_partitioned_table too.
3625  */
3626  if (bound->is_default)
3628  RelationGetRelid(rel));
3629 
3630  /* Make these updates visible */
3632 
3633  /*
3634  * The partition constraint for the default partition depends on the
3635  * partition bounds of every other partition, so we must invalidate the
3636  * relcache entry for that partition every time a partition is added or
3637  * removed.
3638  */
3639  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3640  if (OidIsValid(defaultPartOid))
3641  CacheInvalidateRelcacheByRelid(defaultPartOid);
3642 
3643  CacheInvalidateRelcache(parent);
3644 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:448
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:323
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:645
#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
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1329
bool relispartition
Definition: pg_class.h:117
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1005
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:739
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
#define elog(elevel,...)
Definition: elog.h:228
#define CStringGetTextDatum(s)
Definition: builtins.h:83
char * nodeToString(const void *obj)
Definition: outfuncs.c:4322
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:422
#define RelationGetPartitionDesc(relation)
Definition: rel.h:609
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
Definition: partdesc.c:373

◆ StorePartitionKey()

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

Definition at line 3413 of file heap.c.

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

Referenced by DefineRelation().

3420 {
3421  int i;
3422  int2vector *partattrs_vec;
3423  oidvector *partopclass_vec;
3424  oidvector *partcollation_vec;
3425  Datum partexprDatum;
3426  Relation pg_partitioned_table;
3427  HeapTuple tuple;
3428  Datum values[Natts_pg_partitioned_table];
3429  bool nulls[Natts_pg_partitioned_table];
3430  ObjectAddress myself;
3431  ObjectAddress referenced;
3432 
3433  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3434 
3435  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3436  partattrs_vec = buildint2vector(partattrs, partnatts);
3437  partopclass_vec = buildoidvector(partopclass, partnatts);
3438  partcollation_vec = buildoidvector(partcollation, partnatts);
3439 
3440  /* Convert the expressions (if any) to a text datum */
3441  if (partexprs)
3442  {
3443  char *exprString;
3444 
3445  exprString = nodeToString(partexprs);
3446  partexprDatum = CStringGetTextDatum(exprString);
3447  pfree(exprString);
3448  }
3449  else
3450  partexprDatum = (Datum) 0;
3451 
3452  pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
3453 
3454  MemSet(nulls, false, sizeof(nulls));
3455 
3456  /* Only this can ever be NULL */
3457  if (!partexprDatum)
3458  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3459 
3460  values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
3461  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3462  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3463  values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
3464  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3465  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3466  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3467  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3468 
3469  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3470 
3471  CatalogTupleInsert(pg_partitioned_table, tuple);
3472  table_close(pg_partitioned_table, RowExclusiveLock);
3473 
3474  /* Mark this relation as dependent on a few things as follows */
3475  myself.classId = RelationRelationId;
3476  myself.objectId = RelationGetRelid(rel);
3477  myself.objectSubId = 0;
3478 
3479  /* Operator class and collation per key column */
3480  for (i = 0; i < partnatts; i++)
3481  {
3482  referenced.classId = OperatorClassRelationId;
3483  referenced.objectId = partopclass[i];
3484  referenced.objectSubId = 0;
3485 
3486  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3487 
3488  /* The default collation is pinned, so don't bother recording it */
3489  if (OidIsValid(partcollation[i]) &&
3490  partcollation[i] != DEFAULT_COLLATION_OID)
3491  {
3492  referenced.classId = CollationRelationId;
3493  referenced.objectId = partcollation[i];
3494  referenced.objectSubId = 0;
3495 
3496  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3497  }
3498  }
3499 
3500  /*
3501  * The partitioning columns are made internally dependent on the table,
3502  * because we cannot drop any of them without dropping the whole table.
3503  * (ATExecDropColumn independently enforces that, but it's not bulletproof
3504  * so we need the dependencies too.)
3505  */
3506  for (i = 0; i < partnatts; i++)
3507  {
3508  if (partattrs[i] == 0)
3509  continue; /* ignore expressions here */
3510 
3511  referenced.classId = RelationRelationId;
3512  referenced.objectId = RelationGetRelid(rel);
3513  referenced.objectSubId = partattrs[i];
3514 
3515  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
3516  }
3517 
3518  /*
3519  * Also consider anything mentioned in partition expressions. External
3520  * references (e.g. functions) get NORMAL dependencies. Table columns
3521  * mentioned in the expressions are handled the same as plain partitioning
3522  * columns, i.e. they become internally dependent on the whole table.
3523  */
3524  if (partexprs)
3526  (Node *) partexprs,
3527  RelationGetRelid(rel),
3530  true /* reverse the self-deps */ );
3531 
3532  /*
3533  * We must invalidate the relcache so that the next
3534  * CommandCounterIncrement() will cause the same to be rebuilt using the
3535  * information in just created catalog entry.
3536  */
3538 }
Definition: c.h:595
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define RelationGetDescr(relation)
Definition: rel.h:448
#define PointerGetDatum(X)
Definition: postgres.h:556
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:114
#define Int16GetDatum(X)
Definition: postgres.h:451
Definition: nodes.h:525
#define MemSet(start, val, len)
Definition: c.h:962
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
Form_pg_class rd_rel
Definition: rel.h:83
#define OidIsValid(objectId)
Definition: c.h:645
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define RowExclusiveLock
Definition: lockdefs.h:38
Definition: c.h:584
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:739
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:167
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
Definition: dependency.c:1629
#define CharGetDatum(X)
Definition: postgres.h:416
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:83
char * nodeToString(const void *obj)
Definition: outfuncs.c:4322
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:422
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ StoreRelCheck()

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

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

2315 {
2316  char *ccbin;
2317  List *varList;
2318  int keycount;
2319  int16 *attNos;
2320  Oid constrOid;
2321 
2322  /*
2323  * Flatten expression to string form for storage.
2324  */
2325  ccbin = nodeToString(expr);
2326 
2327  /*
2328  * Find columns of rel that are used in expr
2329  *
2330  * NB: pull_var_clause is okay here only because we don't allow subselects
2331  * in check constraints; it would fail to examine the contents of
2332  * subselects.
2333  */
2334  varList = pull_var_clause(expr, 0);
2335  keycount = list_length(varList);
2336 
2337  if (keycount > 0)
2338  {
2339  ListCell *vl;
2340  int i = 0;
2341 
2342  attNos = (int16 *) palloc(keycount * sizeof(int16));
2343  foreach(vl, varList)
2344  {
2345  Var *var = (Var *) lfirst(vl);
2346  int j;
2347 
2348  for (j = 0; j < i; j++)
2349  if (attNos[j] == var->varattno)
2350  break;
2351  if (j == i)
2352  attNos[i++] = var->varattno;
2353  }
2354  keycount = i;
2355  }
2356  else
2357  attNos = NULL;
2358 
2359  /*
2360  * Partitioned tables do not contain any rows themselves, so a NO INHERIT
2361  * constraint makes no sense.
2362  */
2363  if (is_no_inherit &&
2364  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2365  ereport(ERROR,
2366  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2367  errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
2368  RelationGetRelationName(rel))));
2369 
2370  /*
2371  * Create the Check Constraint
2372  */
2373  constrOid =
2374  CreateConstraintEntry(ccname, /* Constraint Name */
2375  RelationGetNamespace(rel), /* namespace */
2376  CONSTRAINT_CHECK, /* Constraint Type */
2377  false, /* Is Deferrable */
2378  false, /* Is Deferred */
2379  is_validated,
2380  InvalidOid, /* no parent constraint */
2381  RelationGetRelid(rel), /* relation */
2382  attNos, /* attrs in the constraint */
2383  keycount, /* # key attrs in the constraint */
2384  keycount, /* # total attrs in the constraint */
2385  InvalidOid, /* not a domain constraint */
2386  InvalidOid, /* no associated index */
2387  InvalidOid, /* Foreign key fields */
2388  NULL,
2389  NULL,
2390  NULL,
2391  NULL,
2392  0,
2393  ' ',
2394  ' ',
2395  ' ',
2396  NULL, /* not an exclusion constraint */
2397  expr, /* Tree form of check constraint */
2398  ccbin, /* Binary form of check constraint */
2399  is_local, /* conislocal */
2400  inhcount, /* coninhcount */
2401  is_no_inherit, /* connoinherit */
2402  is_internal); /* internally constructed? */
2403 
2404  pfree(ccbin);
2405 
2406  return constrOid;
2407 }
signed short int16
Definition: c.h:346
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:51
int errcode(int sqlerrcode)
Definition: elog.c:608
AttrNumber varattno
Definition: primnodes.h:172
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
Form_pg_class rd_rel
Definition: rel.h:83
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:167
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:456
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvalidOid
Definition: postgres_ext.h:36
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
char * nodeToString(const void *obj)
Definition: outfuncs.c:4322
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:422
#define RelationGetNamespace(relation)
Definition: rel.h:463

◆ SystemAttributeByName()

const FormData_pg_attribute* SystemAttributeByName ( const char *  attname)

Definition at line 262 of file heap.c.

References FormData_pg_attribute, lengthof, NameStr, and SysAtt.

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

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

◆ SystemAttributeDefinition()

const FormData_pg_attribute* SystemAttributeDefinition ( AttrNumber  attno)

Definition at line 250 of file heap.c.

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

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

251 {
252  if (attno >= 0 || attno < -(int) lengthof(SysAtt))
253  elog(ERROR, "invalid system attribute number %d", attno);
254  return SysAtt[-attno - 1];
255 }
#define lengthof(array)
Definition: c.h:669
#define ERROR
Definition: elog.h:43
static const FormData_pg_attribute * SysAtt[]
Definition: heap.c:242
#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 = 'p',
.attalign = 's',
.attnotnull = true,
.attislocal = true,
}
char attstorage
Definition: pg_attribute.h:123
bool attnotnull
Definition: pg_attribute.h:132
bool attbyval
Definition: pg_attribute.h:108
char attalign
Definition: pg_attribute.h:129
int16 attnum
Definition: pg_attribute.h:79
struct ItemPointerData ItemPointerData
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21

Definition at line 152 of file heap.c.

Referenced by aclitem_eq(), aclitemComparator(), cmpaffix(), deccall2(), deccall3(), evalLazyFunc(), inet_merge(), inet_same_family(), macaddr8_cmp(), macaddr8_eq(), macaddr8_ge(), macaddr8_gt(), macaddr8_le(), macaddr8_lt(), macaddr8_ne(), macaddr_cmp(), macaddr_eq(), macaddr_ge(), macaddr_gt(), macaddr_le(), macaddr_lt(), macaddr_ne(), MergeAffix(), network_cmp(), network_eq(), network_ge(), network_gt(), network_larger(), network_le(), network_lt(), network_ne(), network_overlap(), network_smaller(), network_sub(), network_subeq(), network_sup(), and network_supeq().

◆ a2

◆ a3

const FormData_pg_attribute a3
static
Initial value:
= {
.attname = {"cmin"},
.atttypid = CIDOID,
.attlen = sizeof(CommandId),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = true,
.attstorage = 'p',
.attalign = 'i',
.attnotnull = true,
.attislocal = true,
}
uint32 CommandId
Definition: c.h:528
char attstorage
Definition: pg_attribute.h:123
bool attnotnull
Definition: pg_attribute.h:132
#define MinCommandIdAttributeNumber
Definition: sysattr.h:23
bool attbyval
Definition: pg_attribute.h:108
char attalign
Definition: pg_attribute.h:129
int16 attnum
Definition: pg_attribute.h:79

Definition at line 180 of file heap.c.

◆ a4

const FormData_pg_attribute a4
static
Initial value:
= {
.attname = {"xmax"},
.atttypid = XIDOID,
.attlen = sizeof(TransactionId),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = true,
.attstorage = 'p',
.attalign = 'i',
.attnotnull = true,
.attislocal = true,
}
char attstorage
Definition: pg_attribute.h:123
bool attnotnull
Definition: pg_attribute.h:132
uint32 TransactionId
Definition: c.h:514
bool attbyval
Definition: pg_attribute.h:108
char attalign
Definition: pg_attribute.h:129
#define MaxTransactionIdAttributeNumber
Definition: sysattr.h:24
int16 attnum
Definition: pg_attribute.h:79

Definition at line 194 of file heap.c.

◆ a5

const FormData_pg_attribute a5
static
Initial value:
= {
.attname = {"cmax"},
.atttypid = CIDOID,
.attlen = sizeof(CommandId),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = true,
.attstorage = 'p',
.attalign = 'i',
.attnotnull = true,
.attislocal = true,
}
uint32 CommandId
Definition: c.h:528
char attstorage
Definition: pg_attribute.h:123
bool attnotnull
Definition: pg_attribute.h:132
bool attbyval
Definition: pg_attribute.h:108
char attalign
Definition: pg_attribute.h:129
#define MaxCommandIdAttributeNumber
Definition: sysattr.h:25
int16 attnum
Definition: pg_attribute.h:79

Definition at line 208 of file heap.c.

◆ a6

const FormData_pg_attribute a6
static
Initial value:
= {
.attname = {"tableoid"},
.atttypid = OIDOID,
.attlen = sizeof(Oid),
.attcacheoff = -1,
.atttypmod = -1,
.attbyval = true,
.attstorage = 'p',
.attalign = 'i',
.attnotnull = true,
.attislocal = true,
}
char attstorage
Definition: pg_attribute.h:123
bool attnotnull
Definition: pg_attribute.h:132
unsigned int Oid
Definition: postgres_ext.h:31
bool attbyval
Definition: pg_attribute.h:108
char attalign
Definition: pg_attribute.h:129
#define TableOidAttributeNumber
Definition: sysattr.h:26
int16 attnum
Definition: pg_attribute.h:79

Definition at line 228 of file heap.c.

◆ binary_upgrade_next_heap_pg_class_oid

Oid binary_upgrade_next_heap_pg_class_oid = InvalidOid

Definition at line 93 of file heap.c.

Referenced by binary_upgrade_set_next_heap_pg_class_oid(), and heap_create_with_catalog().

◆ binary_upgrade_next_toast_pg_class_oid

Oid binary_upgrade_next_toast_pg_class_oid = InvalidOid

◆ SysAtt

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

Definition at line 242 of file heap.c.

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