PostgreSQL Source Code  git master
heap.h File Reference
Include dependency graph for heap.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  RawColumnDefault
 
struct  CookedConstraint
 

Macros

#define CHKATYPE_ANYARRAY   0x01 /* allow ANYARRAY */
 
#define CHKATYPE_ANYRECORD   0x02 /* allow RECORD and RECORD[] */
 
#define CHKATYPE_IS_PARTKEY   0x04 /* attname is part key # not column */
 

Typedefs

typedef struct RawColumnDefault RawColumnDefault
 
typedef struct CookedConstraint CookedConstraint
 

Functions

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)
 
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 heap_drop_with_catalog (Oid relid)
 
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 InsertPgAttributeTuples (Relation pg_attribute_rel, TupleDesc tupdesc, Oid new_rel_oid, Datum *attoptions, CatalogIndexState indstate)
 
void InsertPgClassTuple (Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
 
ListAddRelationNewConstraints (Relation rel, List *newColDefaults, List *newConstraints, bool allow_merge, bool is_local, bool is_internal, const char *queryString)
 
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)
 
NodecookDefault (ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname, char attgenerated)
 
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 RemoveStatistics (Oid relid, AttrNumber attnum)
 
const FormData_pg_attributeSystemAttributeDefinition (AttrNumber attno)
 
const FormData_pg_attributeSystemAttributeByName (const char *attname)
 
void CheckAttributeNamesTypes (TupleDesc tupdesc, char relkind, int flags)
 
void CheckAttributeType (const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, int flags)
 
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)
 

Macro Definition Documentation

◆ CHKATYPE_ANYARRAY

#define CHKATYPE_ANYARRAY   0x01 /* allow ANYARRAY */

Definition at line 23 of file heap.h.

Referenced by CheckAttributeType(), and heap_create_with_catalog().

◆ CHKATYPE_ANYRECORD

#define CHKATYPE_ANYRECORD   0x02 /* allow RECORD and RECORD[] */

Definition at line 24 of file heap.h.

Referenced by addRangeTableEntryForFunction(), and CheckAttributeType().

◆ CHKATYPE_IS_PARTKEY

#define CHKATYPE_IS_PARTKEY   0x04 /* attname is part key # not column */

Definition at line 25 of file heap.h.

Referenced by CheckAttributeType(), and ComputePartitionAttrs().

Typedef Documentation

◆ CookedConstraint

◆ RawColumnDefault

Function Documentation

◆ AddRelationNewConstraints()

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

Definition at line 2561 of file heap.c.

References AccessShareLock, addNSItemToQuery(), addRangeTableEntryForRelation(), Assert, RawColumnDefault::attnum, CookedConstraint::attnum, castNode, ChooseConstraintName(), Constraint::conname, CookedConstraint::conoid, TupleDescData::constr, CONSTR_CHECK, CONSTR_DEFAULT, contain_volatile_functions(), CookedConstraint::contype, Constraint::contype, cookConstraint(), cookDefault(), Constraint::cooked_expr, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, CookedConstraint::expr, RawColumnDefault::generated, get_attname(), CookedConstraint::inhcount, Constraint::initially_valid, CookedConstraint::is_local, CookedConstraint::is_no_inherit, Constraint::is_no_inherit, IsA, lappend(), lfirst, linitial, list_length(), list_union(), make_parsestate(), MergeWithExistingConstraint(), RawColumnDefault::missingMode, CookedConstraint::name, NameStr, NIL, TupleConstr::num_check, ParseState::p_sourcetext, palloc(), pull_var_clause(), RawColumnDefault::raw_default, Constraint::raw_expr, RelationData::rd_att, RelationGetDescr, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, SetRelationNumChecks(), CookedConstraint::skip_validation, Constraint::skip_validation, StoreAttrDefault(), StoreRelCheck(), stringToNode(), and TupleDescAttr.

Referenced by ATAddCheckConstraint(), ATExecAddColumn(), ATExecColumnDefault(), and DefineRelation().

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

◆ CheckAttributeNamesTypes()

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

Definition at line 489 of file heap.c.

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

Referenced by addRangeTableEntryForFunction(), and heap_create_with_catalog().

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

◆ CheckAttributeType()

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

Definition at line 581 of file heap.c.

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

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

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

◆ cookDefault()

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

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

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

◆ DeleteAttributeTuples()

void DeleteAttributeTuples ( Oid  relid)

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

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

◆ DeleteRelationTuple()

void DeleteRelationTuple ( Oid  relid)

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

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

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

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

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

◆ heap_create()

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

Definition at line 294 of file heap.c.

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

Referenced by heap_create_with_catalog(), and index_create().

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

◆ 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 1137 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, makeArrayTypeName(), moveArrayTypeName(), NoLock, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, ONCOMMIT_NOOP, pfree(), PointerGetDatum, RelationData::rd_att, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnNewAcl(), recordDependencyOnOwner(), register_on_commit_action(), RelationGetRelid, RowExclusiveLock, StoreConstraints(), table_close(), table_open(), TypeCreate(), and TYPENAMENSP.

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

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

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

Definition at line 1897 of file heap.c.

References AccessExclusiveLock, CacheInvalidateRelcacheByRelid(), CatalogTupleDelete(), CheckTableForSerializableConflictIn(), CheckTableNotInUse(), DeleteAttributeTuples(), DeleteRelationTuple(), elog, ERROR, FOREIGNTABLEREL, get_default_partition_oid(), get_partition_parent(), GETSTRUCT, HeapTupleIsValid, InvalidOid, LockRelationOid(), NoLock, ObjectIdGetDatum, OidIsValid, RelationData::rd_rel, relation_close(), relation_open(), RelationDropStorage(), RelationForgetRelation(), RelationRemoveInheritance(), ReleaseSysCache(), RELOID, remove_on_commit_action(), RemovePartitionKeyByRelId(), RemoveStatistics(), RemoveSubscriptionRel(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), table_open(), and update_default_partition_oid().

Referenced by doDeletion().

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

◆ heap_truncate()

void heap_truncate ( List relids)

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

3257 {
3258  List *relations = NIL;
3259  ListCell *cell;
3260 
3261  /* Open relations for processing, and grab exclusive access on each */
3262  foreach(cell, relids)
3263  {
3264  Oid rid = lfirst_oid(cell);
3265  Relation rel;
3266 
3267  rel = table_open(rid, AccessExclusiveLock);
3268  relations = lappend(relations, rel);
3269  }
3270 
3271  /* Don't allow truncate on tables that are referenced by foreign keys */
3272  heap_truncate_check_FKs(relations, true);
3273 
3274  /* OK to do it */
3275  foreach(cell, relations)
3276  {
3277  Relation rel = lfirst(cell);
3278 
3279  /* Truncate the relation */
3280  heap_truncate_one_rel(rel);
3281 
3282  /* Close the relation, but keep exclusive lock on it until commit */
3283  table_close(rel, NoLock);
3284  }
3285 }
#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:3297
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3341
unsigned int Oid
Definition: postgres_ext.h:31
#define NoLock
Definition: lockdefs.h:34
List * lappend(List *list, void *datum)
Definition: list.c:321
#define lfirst(lc)
Definition: pg_list.h:190
#define AccessExclusiveLock
Definition: lockdefs.h:45
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ heap_truncate_check_FKs()

void heap_truncate_check_FKs ( List relations,
bool  tempTables 
)

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

3342 {
3343  List *oids = NIL;
3344  List *dependents;
3345  ListCell *cell;
3346 
3347  /*
3348  * Build a list of OIDs of the interesting relations.
3349  *
3350  * If a relation has no triggers, then it can neither have FKs nor be
3351  * referenced by a FK from another table, so we can ignore it. For
3352  * partitioned tables, FKs have no triggers, so we must include them
3353  * anyway.
3354  */
3355  foreach(cell, relations)
3356  {
3357  Relation rel = lfirst(cell);
3358 
3359  if (rel->rd_rel->relhastriggers ||
3360  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3361  oids = lappend_oid(oids, RelationGetRelid(rel));
3362  }
3363 
3364  /*
3365  * Fast path: if no relation has triggers, none has FKs either.
3366  */
3367  if (oids == NIL)
3368  return;
3369 
3370  /*
3371  * Otherwise, must scan pg_constraint. We make one pass with all the
3372  * relations considered; if this finds nothing, then all is well.
3373  */
3374  dependents = heap_truncate_find_FKs(oids);
3375  if (dependents == NIL)
3376  return;
3377 
3378  /*
3379  * Otherwise we repeat the scan once per relation to identify a particular
3380  * pair of relations to complain about. This is pretty slow, but
3381  * performance shouldn't matter much in a failure path. The reason for
3382  * doing things this way is to ensure that the message produced is not
3383  * dependent on chance row locations within pg_constraint.
3384  */
3385  foreach(cell, oids)
3386  {
3387  Oid relid = lfirst_oid(cell);
3388  ListCell *cell2;
3389 
3390  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
3391 
3392  foreach(cell2, dependents)
3393  {
3394  Oid relid2 = lfirst_oid(cell2);
3395 
3396  if (!list_member_oid(oids, relid2))
3397  {
3398  char *relname = get_rel_name(relid);
3399  char *relname2 = get_rel_name(relid2);
3400 
3401  if (tempTables)
3402  ereport(ERROR,
3403  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3404  errmsg("unsupported ON COMMIT and foreign key combination"),
3405  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3406  relname2, relname)));
3407  else
3408  ereport(ERROR,
3409  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3410  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3411  errdetail("Table \"%s\" references \"%s\".",
3412  relname2, relname),
3413  errhint("Truncate table \"%s\" at the same time, "
3414  "or use TRUNCATE ... CASCADE.",
3415  relname2)));
3416  }
3417  }
3418  }
3419 }
#define NIL
Definition: pg_list.h:65
int errhint(const char *fmt,...)
Definition: elog.c:1071
int errcode(int sqlerrcode)
Definition: elog.c:610
Form_pg_class rd_rel
Definition: rel.h:109
NameData relname
Definition: pg_class.h:38
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:957
#define list_make1_oid(x1)
Definition: pg_list.h:249
#define ereport(elevel,...)
Definition: elog.h:144
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:674
#define lfirst(lc)
Definition: pg_list.h:190
int errmsg(const char *fmt,...)
Definition: elog.c:824
Definition: pg_list.h:50
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1840
#define RelationGetRelid(relation)
Definition: rel.h:456
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3436
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

Definition at line 3436 of file heap.c.

References AccessShareLock, BTEqualStrategyNumber, ConstraintOidIndexId, GETSTRUCT, HeapTupleIsValid, InvalidOid, sort-test::key, lappend_oid(), lfirst_oid, list_append_unique_oid(), list_copy(), list_deduplicate_oid(), list_free(), list_member_oid(), list_oid_cmp(), list_sort(), NIL, ObjectIdGetDatum, OidIsValid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ExecuteTruncateGuts(), and heap_truncate_check_FKs().

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

◆ heap_truncate_one_rel()

void heap_truncate_one_rel ( Relation  rel)

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

3298 {
3299  Oid toastrelid;
3300 
3301  /*
3302  * Truncate the relation. Partitioned tables have no storage, so there is
3303  * nothing to do for them here.
3304  */
3305  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3306  return;
3307 
3308  /* Truncate the underlying relation */
3310 
3311  /* If the relation has indexes, truncate the indexes too */
3313 
3314  /* If there is a toast table, truncate that too */
3315  toastrelid = rel->rd_rel->reltoastrelid;
3316  if (OidIsValid(toastrelid))
3317  {
3318  Relation toastrel = table_open(toastrelid, AccessExclusiveLock);
3319 
3321  RelationTruncateIndexes(toastrel);
3322  /* keep the lock... */
3323  table_close(toastrel, NoLock);
3324  }
3325 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
static void table_relation_nontransactional_truncate(Relation rel)
Definition: tableam.h:1389
#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:3208

◆ InsertPgAttributeTuples()

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

Definition at line 736 of file heap.c.

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

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

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

◆ InsertPgClassTuple()

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

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

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

◆ RelationClearMissing()

void RelationClearMissing ( Relation  rel)

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

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

◆ RemoveAttrDefault()

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

Definition at line 1769 of file heap.c.

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

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

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

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

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

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

◆ RemoveAttributeById()

void RemoveAttributeById ( Oid  relid,
AttrNumber  attnum 
)

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

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

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

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

3697 {
3698  Relation rel;
3699  HeapTuple tuple;
3700 
3701  rel = table_open(PartitionedRelationId, RowExclusiveLock);
3702 
3703  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3704  if (!HeapTupleIsValid(tuple))
3705  elog(ERROR, "cache lookup failed for partition key of relation %u",
3706  relid);
3707 
3708  CatalogTupleDelete(rel, &tuple->t_self);
3709 
3710  ReleaseSysCache(tuple);
3712 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

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

3162 {
3163  Relation pgstatistic;
3164  SysScanDesc scan;
3165  ScanKeyData key[2];
3166  int nkeys;
3167  HeapTuple tuple;
3168 
3169  pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
3170 
3171  ScanKeyInit(&key[0],
3172  Anum_pg_statistic_starelid,
3173  BTEqualStrategyNumber, F_OIDEQ,
3174  ObjectIdGetDatum(relid));
3175 
3176  if (attnum == 0)
3177  nkeys = 1;
3178  else
3179  {
3180  ScanKeyInit(&key[1],
3181  Anum_pg_statistic_staattnum,
3182  BTEqualStrategyNumber, F_INT2EQ,
3184  nkeys = 2;
3185  }
3186 
3187  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
3188  NULL, nkeys, key);
3189 
3190  /* we must loop even when attnum != 0, in case of inherited stats */
3191  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3192  CatalogTupleDelete(pgstatistic, &tuple->t_self);
3193 
3194  systable_endscan(scan);
3195 
3196  table_close(pgstatistic, RowExclusiveLock);
3197 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define Int16GetDatum(X)
Definition: postgres.h:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define StatisticRelidAttnumInhIndexId
Definition: indexing.h:233
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 2137 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().

2138 {
2139  Datum valuesAtt[Natts_pg_attribute];
2140  bool nullsAtt[Natts_pg_attribute];
2141  bool replacesAtt[Natts_pg_attribute];
2142  Datum missingval;
2143  Form_pg_attribute attStruct;
2144  Relation attrrel,
2145  tablerel;
2146  HeapTuple atttup,
2147  newtup;
2148 
2149  /* lock the table the attribute belongs to */
2150  tablerel = table_open(relid, AccessExclusiveLock);
2151 
2152  /* Lock the attribute row and get the data */
2153  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2154  atttup = SearchSysCacheAttName(relid, attname);
2155  if (!HeapTupleIsValid(atttup))
2156  elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2157  attname, relid);
2158  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2159 
2160  /* get an array value from the value string */
2161  missingval = OidFunctionCall3(F_ARRAY_IN,
2163  ObjectIdGetDatum(attStruct->atttypid),
2164  Int32GetDatum(attStruct->atttypmod));
2165 
2166  /* update the tuple - set atthasmissing and attmissingval */
2167  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2168  MemSet(nullsAtt, false, sizeof(nullsAtt));
2169  MemSet(replacesAtt, false, sizeof(replacesAtt));
2170 
2171  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
2172  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2173  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2174  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2175 
2176  newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2177  valuesAtt, nullsAtt, replacesAtt);
2178  CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
2179 
2180  /* clean up */
2181  ReleaseSysCache(atttup);
2182  table_close(attrrel, RowExclusiveLock);
2183  table_close(tablerel, AccessExclusiveLock);
2184 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:482
#define MemSet(start, val, len)
Definition: c.h:978
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition: fmgr.h:666
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define BoolGetDatum(X)
Definition: postgres.h:402
static struct @143 value
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1257
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define Int32GetDatum(X)
Definition: postgres.h:479
#define elog(elevel,...)
Definition: elog.h:214
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113

◆ StoreAttrDefault()

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

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

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

◆ StorePartitionBound()

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

Definition at line 3727 of file heap.c.

References Assert, CacheInvalidateRelcache(), CacheInvalidateRelcacheByRelid(), CatalogTupleUpdate(), CommandCounterIncrement(), CStringGetTextDatum, elog, ERROR, get_default_oid_from_partdesc(), GETSTRUCT, heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, PartitionBoundSpec::is_default, nodeToString(), ObjectIdGetDatum, OidIsValid, RelationGetDescr, RelationGetPartitionDesc(), RelationGetRelid, RELOID, RowExclusiveLock, SearchSysCacheCopy1, SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), and update_default_partition_oid().

Referenced by ATExecAttachPartition(), and DefineRelation().

3728 {
3729  Relation classRel;
3730  HeapTuple tuple,
3731  newtuple;
3732  Datum new_val[Natts_pg_class];
3733  bool new_null[Natts_pg_class],
3734  new_repl[Natts_pg_class];
3735  Oid defaultPartOid;
3736 
3737  /* Update pg_class tuple */
3738  classRel = table_open(RelationRelationId, RowExclusiveLock);
3739  tuple = SearchSysCacheCopy1(RELOID,
3741  if (!HeapTupleIsValid(tuple))
3742  elog(ERROR, "cache lookup failed for relation %u",
3743  RelationGetRelid(rel));
3744 
3745 #ifdef USE_ASSERT_CHECKING
3746  {
3747  Form_pg_class classForm;
3748  bool isnull;
3749 
3750  classForm = (Form_pg_class) GETSTRUCT(tuple);
3751  Assert(!classForm->relispartition);
3752  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3753  &isnull);
3754  Assert(isnull);
3755  }
3756 #endif
3757 
3758  /* Fill in relpartbound value */
3759  memset(new_val, 0, sizeof(new_val));
3760  memset(new_null, false, sizeof(new_null));
3761  memset(new_repl, false, sizeof(new_repl));
3762  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3763  new_null[Anum_pg_class_relpartbound - 1] = false;
3764  new_repl[Anum_pg_class_relpartbound - 1] = true;
3765  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3766  new_val, new_null, new_repl);
3767  /* Also set the flag */
3768  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3769  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3770  heap_freetuple(newtuple);
3771  table_close(classRel, RowExclusiveLock);
3772 
3773  /*
3774  * If we're storing bounds for the default partition, update
3775  * pg_partitioned_table too.
3776  */
3777  if (bound->is_default)
3779  RelationGetRelid(rel));
3780 
3781  /* Make these updates visible */
3783 
3784  /*
3785  * The partition constraint for the default partition depends on the
3786  * partition bounds of every other partition, so we must invalidate the
3787  * relcache entry for that partition every time a partition is added or
3788  * removed.
3789  */
3790  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3791  if (OidIsValid(defaultPartOid))
3792  CacheInvalidateRelcacheByRelid(defaultPartOid);
3793 
3794  CacheInvalidateRelcache(parent);
3795 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:482
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:315
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
PartitionDesc RelationGetPartitionDesc(Relation rel)
Definition: partdesc.c:65
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1337
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1008
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:745
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
#define elog(elevel,...)
Definition: elog.h:214
#define CStringGetTextDatum(s)
Definition: builtins.h:87
char * nodeToString(const void *obj)
Definition: outfuncs.c:4360
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define RelationGetRelid(relation)
Definition: rel.h:456
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
Definition: partdesc.c:361

◆ StorePartitionKey()

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

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

3571 {
3572  int i;
3573  int2vector *partattrs_vec;
3574  oidvector *partopclass_vec;
3575  oidvector *partcollation_vec;
3576  Datum partexprDatum;
3577  Relation pg_partitioned_table;
3578  HeapTuple tuple;
3579  Datum values[Natts_pg_partitioned_table];
3580  bool nulls[Natts_pg_partitioned_table];
3581  ObjectAddress myself;
3582  ObjectAddress referenced;
3583 
3584  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3585 
3586  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3587  partattrs_vec = buildint2vector(partattrs, partnatts);
3588  partopclass_vec = buildoidvector(partopclass, partnatts);
3589  partcollation_vec = buildoidvector(partcollation, partnatts);
3590 
3591  /* Convert the expressions (if any) to a text datum */
3592  if (partexprs)
3593  {
3594  char *exprString;
3595 
3596  exprString = nodeToString(partexprs);
3597  partexprDatum = CStringGetTextDatum(exprString);
3598  pfree(exprString);
3599  }
3600  else
3601  partexprDatum = (Datum) 0;
3602 
3603  pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
3604 
3605  MemSet(nulls, false, sizeof(nulls));
3606 
3607  /* Only this can ever be NULL */
3608  if (!partexprDatum)
3609  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3610 
3611  values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
3612  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3613  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3614  values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
3615  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3616  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3617  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3618  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3619 
3620  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3621 
3622  CatalogTupleInsert(pg_partitioned_table, tuple);
3623  table_close(pg_partitioned_table, RowExclusiveLock);
3624 
3625  /* Mark this relation as dependent on a few things as follows */
3626  myself.classId = RelationRelationId;
3627  myself.objectId = RelationGetRelid(rel);
3628  myself.objectSubId = 0;
3629 
3630  /* Operator class and collation per key column */
3631  for (i = 0; i < partnatts; i++)
3632  {
3633  referenced.classId = OperatorClassRelationId;
3634  referenced.objectId = partopclass[i];
3635  referenced.objectSubId = 0;
3636 
3637  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3638 
3639  /* The default collation is pinned, so don't bother recording it */
3640  if (OidIsValid(partcollation[i]) &&
3641  partcollation[i] != DEFAULT_COLLATION_OID)
3642  {
3643  referenced.classId = CollationRelationId;
3644  referenced.objectId = partcollation[i];
3645  referenced.objectSubId = 0;
3646 
3647  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3648  }
3649  }
3650 
3651  /*
3652  * The partitioning columns are made internally dependent on the table,
3653  * because we cannot drop any of them without dropping the whole table.
3654  * (ATExecDropColumn independently enforces that, but it's not bulletproof
3655  * so we need the dependencies too.)
3656  */
3657  for (i = 0; i < partnatts; i++)
3658  {
3659  if (partattrs[i] == 0)
3660  continue; /* ignore expressions here */
3661 
3662  referenced.classId = RelationRelationId;
3663  referenced.objectId = RelationGetRelid(rel);
3664  referenced.objectSubId = partattrs[i];
3665 
3666  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
3667  }
3668 
3669  /*
3670  * Also consider anything mentioned in partition expressions. External
3671  * references (e.g. functions) get NORMAL dependencies. Table columns
3672  * mentioned in the expressions are handled the same as plain partitioning
3673  * columns, i.e. they become internally dependent on the whole table.
3674  */
3675  if (partexprs)
3677  (Node *) partexprs,
3678  RelationGetRelid(rel),
3681  true /* reverse the self-deps */ );
3682 
3683  /*
3684  * We must invalidate the relcache so that the next
3685  * CommandCounterIncrement() will cause the same to be rebuilt using the
3686  * information in just created catalog entry.
3687  */
3689 }
Definition: c.h:601
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define RelationGetDescr(relation)
Definition: rel.h:482
#define PointerGetDatum(X)
Definition: postgres.h:556
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:114
#define Int16GetDatum(X)
Definition: postgres.h:451
Definition: nodes.h:529
#define MemSet(start, val, len)
Definition: c.h:978
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:43
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
Form_pg_class rd_rel
Definition: rel.h:109
#define OidIsValid(objectId)
Definition: c.h:651
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define RowExclusiveLock
Definition: lockdefs.h:38
Definition: c.h:590
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:745
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:1627
#define CharGetDatum(X)
Definition: postgres.h:416
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:87
char * nodeToString(const void *obj)
Definition: outfuncs.c:4360
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:456
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ SystemAttributeByName()

const FormData_pg_attribute* SystemAttributeByName ( const char *  attname)

Definition at line 261 of file heap.c.

References FormData_pg_attribute, lengthof, NameStr, and SysAtt.

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

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

◆ SystemAttributeDefinition()

const FormData_pg_attribute* SystemAttributeDefinition ( AttrNumber  attno)

Definition at line 249 of file heap.c.

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

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

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