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 InsertPgAttributeTuple (Relation pg_attribute_rel, Form_pg_attribute new_attribute, 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 2523 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().

2530 {
2531  List *cookedConstraints = NIL;
2532  TupleDesc tupleDesc;
2533  TupleConstr *oldconstr;
2534  int numoldchecks;
2535  ParseState *pstate;
2536  ParseNamespaceItem *nsitem;
2537  int numchecks;
2538  List *checknames;
2539  ListCell *cell;
2540  Node *expr;
2541  CookedConstraint *cooked;
2542 
2543  /*
2544  * Get info about existing constraints.
2545  */
2546  tupleDesc = RelationGetDescr(rel);
2547  oldconstr = tupleDesc->constr;
2548  if (oldconstr)
2549  numoldchecks = oldconstr->num_check;
2550  else
2551  numoldchecks = 0;
2552 
2553  /*
2554  * Create a dummy ParseState and insert the target relation as its sole
2555  * rangetable entry. We need a ParseState for transformExpr.
2556  */
2557  pstate = make_parsestate(NULL);
2558  pstate->p_sourcetext = queryString;
2559  nsitem = addRangeTableEntryForRelation(pstate,
2560  rel,
2562  NULL,
2563  false,
2564  true);
2565  addNSItemToQuery(pstate, nsitem, true, true, true);
2566 
2567  /*
2568  * Process column default expressions.
2569  */
2570  foreach(cell, newColDefaults)
2571  {
2572  RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
2573  Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
2574  Oid defOid;
2575 
2576  expr = cookDefault(pstate, colDef->raw_default,
2577  atp->atttypid, atp->atttypmod,
2578  NameStr(atp->attname),
2579  atp->attgenerated);
2580 
2581  /*
2582  * If the expression is just a NULL constant, we do not bother to make
2583  * an explicit pg_attrdef entry, since the default behavior is
2584  * equivalent. This applies to column defaults, but not for
2585  * generation expressions.
2586  *
2587  * Note a nonobvious property of this test: if the column is of a
2588  * domain type, what we'll get is not a bare null Const but a
2589  * CoerceToDomain expr, so we will not discard the default. This is
2590  * critical because the column default needs to be retained to
2591  * override any default that the domain might have.
2592  */
2593  if (expr == NULL ||
2594  (!colDef->generated &&
2595  IsA(expr, Const) &&
2596  castNode(Const, expr)->constisnull))
2597  continue;
2598 
2599  /* If the DEFAULT is volatile we cannot use a missing value */
2600  if (colDef->missingMode && contain_volatile_functions((Node *) expr))
2601  colDef->missingMode = false;
2602 
2603  defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal,
2604  colDef->missingMode);
2605 
2606  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2607  cooked->contype = CONSTR_DEFAULT;
2608  cooked->conoid = defOid;
2609  cooked->name = NULL;
2610  cooked->attnum = colDef->attnum;
2611  cooked->expr = expr;
2612  cooked->skip_validation = false;
2613  cooked->is_local = is_local;
2614  cooked->inhcount = is_local ? 0 : 1;
2615  cooked->is_no_inherit = false;
2616  cookedConstraints = lappend(cookedConstraints, cooked);
2617  }
2618 
2619  /*
2620  * Process constraint expressions.
2621  */
2622  numchecks = numoldchecks;
2623  checknames = NIL;
2624  foreach(cell, newConstraints)
2625  {
2626  Constraint *cdef = (Constraint *) lfirst(cell);
2627  char *ccname;
2628  Oid constrOid;
2629 
2630  if (cdef->contype != CONSTR_CHECK)
2631  continue;
2632 
2633  if (cdef->raw_expr != NULL)
2634  {
2635  Assert(cdef->cooked_expr == NULL);
2636 
2637  /*
2638  * Transform raw parsetree to executable expression, and verify
2639  * it's valid as a CHECK constraint.
2640  */
2641  expr = cookConstraint(pstate, cdef->raw_expr,
2643  }
2644  else
2645  {
2646  Assert(cdef->cooked_expr != NULL);
2647 
2648  /*
2649  * Here, we assume the parser will only pass us valid CHECK
2650  * expressions, so we do no particular checking.
2651  */
2652  expr = stringToNode(cdef->cooked_expr);
2653  }
2654 
2655  /*
2656  * Check name uniqueness, or generate a name if none was given.
2657  */
2658  if (cdef->conname != NULL)
2659  {
2660  ListCell *cell2;
2661 
2662  ccname = cdef->conname;
2663  /* Check against other new constraints */
2664  /* Needed because we don't do CommandCounterIncrement in loop */
2665  foreach(cell2, checknames)
2666  {
2667  if (strcmp((char *) lfirst(cell2), ccname) == 0)
2668  ereport(ERROR,
2670  errmsg("check constraint \"%s\" already exists",
2671  ccname)));
2672  }
2673 
2674  /* save name for future checks */
2675  checknames = lappend(checknames, ccname);
2676 
2677  /*
2678  * Check against pre-existing constraints. If we are allowed to
2679  * merge with an existing constraint, there's no more to do here.
2680  * (We omit the duplicate constraint from the result, which is
2681  * what ATAddCheckConstraint wants.)
2682  */
2683  if (MergeWithExistingConstraint(rel, ccname, expr,
2684  allow_merge, is_local,
2685  cdef->initially_valid,
2686  cdef->is_no_inherit))
2687  continue;
2688  }
2689  else
2690  {
2691  /*
2692  * When generating a name, we want to create "tab_col_check" for a
2693  * column constraint and "tab_check" for a table constraint. We
2694  * no longer have any info about the syntactic positioning of the
2695  * constraint phrase, so we approximate this by seeing whether the
2696  * expression references more than one column. (If the user
2697  * played by the rules, the result is the same...)
2698  *
2699  * Note: pull_var_clause() doesn't descend into sublinks, but we
2700  * eliminated those above; and anyway this only needs to be an
2701  * approximate answer.
2702  */
2703  List *vars;
2704  char *colname;
2705 
2706  vars = pull_var_clause(expr, 0);
2707 
2708  /* eliminate duplicates */
2709  vars = list_union(NIL, vars);
2710 
2711  if (list_length(vars) == 1)
2712  colname = get_attname(RelationGetRelid(rel),
2713  ((Var *) linitial(vars))->varattno,
2714  true);
2715  else
2716  colname = NULL;
2717 
2719  colname,
2720  "check",
2721  RelationGetNamespace(rel),
2722  checknames);
2723 
2724  /* save name for future checks */
2725  checknames = lappend(checknames, ccname);
2726  }
2727 
2728  /*
2729  * OK, store it.
2730  */
2731  constrOid =
2732  StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
2733  is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
2734 
2735  numchecks++;
2736 
2737  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2738  cooked->contype = CONSTR_CHECK;
2739  cooked->conoid = constrOid;
2740  cooked->name = ccname;
2741  cooked->attnum = 0;
2742  cooked->expr = expr;
2743  cooked->skip_validation = cdef->skip_validation;
2744  cooked->is_local = is_local;
2745  cooked->inhcount = is_local ? 0 : 1;
2746  cooked->is_no_inherit = cdef->is_no_inherit;
2747  cookedConstraints = lappend(cookedConstraints, cooked);
2748  }
2749 
2750  /*
2751  * Update the count of constraints in the relation's pg_class tuple. We do
2752  * this even if there was no change, in order to ensure that an SI update
2753  * message is sent out for the pg_class tuple, which will force other
2754  * backends to rebuild their relcache entries for the rel. (This is
2755  * critical if we added defaults but not constraints.)
2756  */
2757  SetRelationNumChecks(rel, numchecks);
2758 
2759  return cookedConstraints;
2760 }
#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:2923
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:3081
#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:3006
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:2160
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:2773
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:738
#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:615
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:776
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:2345
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:615
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:2587
#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:2468
char * format_type_be(Oid type_oid)
Definition: format_type.c:327
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:644
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2560
#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:3222
#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:615
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:2360
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:2909
Oid get_range_subtype(Oid rangeOid)
Definition: lsyscache.c:3196

◆ cookDefault()

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

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

3012 {
3013  Node *expr;
3014 
3015  Assert(raw_default != NULL);
3016 
3017  /*
3018  * Transform raw parsetree to executable expression.
3019  */
3020  expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
3021 
3022  if (attgenerated)
3023  {
3024  check_nested_generated(pstate, expr);
3025 
3026  if (contain_mutable_functions(expr))
3027  ereport(ERROR,
3028  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3029  errmsg("generation expression is not immutable")));
3030  }
3031  else
3032  {
3033  /*
3034  * For a default expression, transformExpr() should have rejected
3035  * column references.
3036  */
3037  Assert(!contain_var_clause(expr));
3038  }
3039 
3040  /*
3041  * Coerce the expression to the correct type and typmod, if given. This
3042  * should match the parser's processing of non-defaulted expressions ---
3043  * see transformAssignedExpr().
3044  */
3045  if (OidIsValid(atttypid))
3046  {
3047  Oid type_id = exprType(expr);
3048 
3049  expr = coerce_to_target_type(pstate, expr, type_id,
3050  atttypid, atttypmod,
3053  -1);
3054  if (expr == NULL)
3055  ereport(ERROR,
3056  (errcode(ERRCODE_DATATYPE_MISMATCH),
3057  errmsg("column \"%s\" is of type %s"
3058  " but default expression is of type %s",
3059  attname,
3061  format_type_be(type_id)),
3062  errhint("You will need to rewrite or cast the expression.")));
3063  }
3064 
3065  /*
3066  * Finally, take care of collations in the finished expression.
3067  */
3068  assign_expr_collations(pstate, expr);
3069 
3070  return expr;
3071 }
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:327
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
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:738
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
static void check_nested_generated(ParseState *pstate, Node *node)
Definition: heap.c:2988
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 1535 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().

1536 {
1537  Relation attrel;
1538  SysScanDesc scan;
1539  ScanKeyData key[1];
1540  HeapTuple atttup;
1541 
1542  /* Grab an appropriate lock on the pg_attribute relation */
1543  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1544 
1545  /* Use the index to scan only attributes of the target relation */
1546  ScanKeyInit(&key[0],
1547  Anum_pg_attribute_attrelid,
1548  BTEqualStrategyNumber, F_OIDEQ,
1549  ObjectIdGetDatum(relid));
1550 
1551  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1552  NULL, 1, key);
1553 
1554  /* Delete all the matching tuples */
1555  while ((atttup = systable_getnext(scan)) != NULL)
1556  CatalogTupleDelete(attrel, &atttup->t_self);
1557 
1558  /* Clean up after the scan */
1559  systable_endscan(scan);
1560  table_close(attrel, RowExclusiveLock);
1561 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c: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 1506 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().

1507 {
1508  Relation pg_class_desc;
1509  HeapTuple tup;
1510 
1511  /* Grab an appropriate lock on the pg_class relation */
1512  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1513 
1514  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1515  if (!HeapTupleIsValid(tup))
1516  elog(ERROR, "cache lookup failed for relation %u", relid);
1517 
1518  /* delete the relation tuple from pg_class, and finish up */
1519  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1520 
1521  ReleaseSysCache(tup);
1522 
1523  table_close(pg_class_desc, RowExclusiveLock);
1524 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

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

1573 {
1574  Relation attrel;
1575  SysScanDesc scan;
1576  ScanKeyData key[2];
1577  HeapTuple atttup;
1578 
1579  /* Grab an appropriate lock on the pg_attribute relation */
1580  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1581 
1582  /* Use the index to scan only system attributes of the target relation */
1583  ScanKeyInit(&key[0],
1584  Anum_pg_attribute_attrelid,
1585  BTEqualStrategyNumber, F_OIDEQ,
1586  ObjectIdGetDatum(relid));
1587  ScanKeyInit(&key[1],
1588  Anum_pg_attribute_attnum,
1589  BTLessEqualStrategyNumber, F_INT2LE,
1590  Int16GetDatum(0));
1591 
1592  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1593  NULL, 2, key);
1594 
1595  /* Delete all the matching tuples */
1596  while ((atttup = systable_getnext(scan)) != NULL)
1597  CatalogTupleDelete(attrel, &atttup->t_self);
1598 
1599  /* Clean up after the scan */
1600  systable_endscan(scan);
1601  table_close(attrel, RowExclusiveLock);
1602 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define Int16GetDatum(X)
Definition: postgres.h:451
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c: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:644
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:3155
#define IsNormalProcessingMode()
Definition: miscadmin.h:394
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:738
static void table_relation_set_new_filenode(Relation rel, const RelFileNode *newrnode, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition: tableam.h:1369
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:3335

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

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

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

1120 {
1121  Relation pg_class_desc;
1122  Relation new_rel_desc;
1123  Acl *relacl;
1124  Oid existing_relid;
1125  Oid old_type_oid;
1126  Oid new_type_oid;
1127  ObjectAddress new_type_addr;
1128  Oid new_array_oid = InvalidOid;
1129  TransactionId relfrozenxid;
1130  MultiXactId relminmxid;
1131 
1132  pg_class_desc = table_open(RelationRelationId, RowExclusiveLock);
1133 
1134  /*
1135  * sanity checks
1136  */
1138 
1139  /*
1140  * Validate proposed tupdesc for the desired relkind. If
1141  * allow_system_table_mods is on, allow ANYARRAY to be used; this is a
1142  * hack to allow creating pg_statistic and cloning it during VACUUM FULL.
1143  */
1144  CheckAttributeNamesTypes(tupdesc, relkind,
1145  allow_system_table_mods ? CHKATYPE_ANYARRAY : 0);
1146 
1147  /*
1148  * This would fail later on anyway, if the relation already exists. But
1149  * by catching it here we can emit a nicer error message.
1150  */
1151  existing_relid = get_relname_relid(relname, relnamespace);
1152  if (existing_relid != InvalidOid)
1153  ereport(ERROR,
1154  (errcode(ERRCODE_DUPLICATE_TABLE),
1155  errmsg("relation \"%s\" already exists", relname)));
1156 
1157  /*
1158  * Since we are going to create a rowtype as well, also check for
1159  * collision with an existing type name. If there is one and it's an
1160  * autogenerated array, we can rename it out of the way; otherwise we can
1161  * at least give a good error message.
1162  */
1163  old_type_oid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
1165  ObjectIdGetDatum(relnamespace));
1166  if (OidIsValid(old_type_oid))
1167  {
1168  if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
1169  ereport(ERROR,
1171  errmsg("type \"%s\" already exists", relname),
1172  errhint("A relation has an associated type of the same name, "
1173  "so you must use a name that doesn't conflict "
1174  "with any existing type.")));
1175  }
1176 
1177  /*
1178  * Shared relations must be in pg_global (last-ditch check)
1179  */
1180  if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
1181  elog(ERROR, "shared relations must be placed in pg_global tablespace");
1182 
1183  /*
1184  * Allocate an OID for the relation, unless we were told what to use.
1185  *
1186  * The OID will be the relfilenode as well, so make sure it doesn't
1187  * collide with either pg_class OIDs or existing physical files.
1188  */
1189  if (!OidIsValid(relid))
1190  {
1191  /* Use binary-upgrade override for pg_class.oid/relfilenode? */
1192  if (IsBinaryUpgrade &&
1193  (relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
1194  relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
1195  relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE ||
1196  relkind == RELKIND_PARTITIONED_TABLE))
1197  {
1199  ereport(ERROR,
1200  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1201  errmsg("pg_class heap OID value not set when in binary upgrade mode")));
1202 
1205  }
1206  /* There might be no TOAST table, so we have to test for it. */
1207  else if (IsBinaryUpgrade &&
1209  relkind == RELKIND_TOASTVALUE)
1210  {
1213  }
1214  else
1215  relid = GetNewRelFileNode(reltablespace, pg_class_desc,
1216  relpersistence);
1217  }
1218 
1219  /*
1220  * Determine the relation's initial permissions.
1221  */
1222  if (use_user_acl)
1223  {
1224  switch (relkind)
1225  {
1226  case RELKIND_RELATION:
1227  case RELKIND_VIEW:
1228  case RELKIND_MATVIEW:
1229  case RELKIND_FOREIGN_TABLE:
1230  case RELKIND_PARTITIONED_TABLE:
1231  relacl = get_user_default_acl(OBJECT_TABLE, ownerid,
1232  relnamespace);
1233  break;
1234  case RELKIND_SEQUENCE:
1235  relacl = get_user_default_acl(OBJECT_SEQUENCE, ownerid,
1236  relnamespace);
1237  break;
1238  default:
1239  relacl = NULL;
1240  break;
1241  }
1242  }
1243  else
1244  relacl = NULL;
1245 
1246  /*
1247  * Create the relcache entry (mostly dummy at this point) and the physical
1248  * disk file. (If we fail further down, it's the smgr's responsibility to
1249  * remove the disk file again.)
1250  */
1251  new_rel_desc = heap_create(relname,
1252  relnamespace,
1253  reltablespace,
1254  relid,
1255  InvalidOid,
1256  accessmtd,
1257  tupdesc,
1258  relkind,
1259  relpersistence,
1260  shared_relation,
1261  mapped_relation,
1262  allow_system_table_mods,
1263  &relfrozenxid,
1264  &relminmxid);
1265 
1266  Assert(relid == RelationGetRelid(new_rel_desc));
1267 
1268  new_rel_desc->rd_rel->relrewrite = relrewrite;
1269 
1270  /*
1271  * Decide whether to create an array type over the relation's rowtype. We
1272  * do not create any array types for system catalogs (ie, those made
1273  * during initdb). We do not create them where the use of a relation as
1274  * such is an implementation detail: toast tables, sequences and indexes.
1275  */
1276  if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
1277  relkind == RELKIND_VIEW ||
1278  relkind == RELKIND_MATVIEW ||
1279  relkind == RELKIND_FOREIGN_TABLE ||
1280  relkind == RELKIND_COMPOSITE_TYPE ||
1281  relkind == RELKIND_PARTITIONED_TABLE))
1282  new_array_oid = AssignTypeArrayOid();
1283 
1284  /*
1285  * Since defining a relation also defines a complex type, we add a new
1286  * system type corresponding to the new relation. The OID of the type can
1287  * be preselected by the caller, but if reltypeid is InvalidOid, we'll
1288  * generate a new OID for it.
1289  *
1290  * NOTE: we could get a unique-index failure here, in case someone else is
1291  * creating the same type name in parallel but hadn't committed yet when
1292  * we checked for a duplicate name above.
1293  */
1294  new_type_addr = AddNewRelationType(relname,
1295  relnamespace,
1296  relid,
1297  relkind,
1298  ownerid,
1299  reltypeid,
1300  new_array_oid);
1301  new_type_oid = new_type_addr.objectId;
1302  if (typaddress)
1303  *typaddress = new_type_addr;
1304 
1305  /*
1306  * Now make the array type if wanted.
1307  */
1308  if (OidIsValid(new_array_oid))
1309  {
1310  char *relarrayname;
1311 
1312  relarrayname = makeArrayTypeName(relname, relnamespace);
1313 
1314  TypeCreate(new_array_oid, /* force the type's OID to this */
1315  relarrayname, /* Array type name */
1316  relnamespace, /* Same namespace as parent */
1317  InvalidOid, /* Not composite, no relationOid */
1318  0, /* relkind, also N/A here */
1319  ownerid, /* owner's ID */
1320  -1, /* Internal size (varlena) */
1321  TYPTYPE_BASE, /* Not composite - typelem is */
1322  TYPCATEGORY_ARRAY, /* type-category (array) */
1323  false, /* array types are never preferred */
1324  DEFAULT_TYPDELIM, /* default array delimiter */
1325  F_ARRAY_IN, /* array input proc */
1326  F_ARRAY_OUT, /* array output proc */
1327  F_ARRAY_RECV, /* array recv (bin) proc */
1328  F_ARRAY_SEND, /* array send (bin) proc */
1329  InvalidOid, /* typmodin procedure - none */
1330  InvalidOid, /* typmodout procedure - none */
1331  F_ARRAY_TYPANALYZE, /* array analyze procedure */
1332  new_type_oid, /* array element type - the rowtype */
1333  true, /* yes, this is an array type */
1334  InvalidOid, /* this has no array type */
1335  InvalidOid, /* domain base type - irrelevant */
1336  NULL, /* default value - none */
1337  NULL, /* default binary representation */
1338  false, /* passed by reference */
1339  TYPALIGN_DOUBLE, /* alignment - must be the largest! */
1340  TYPSTORAGE_EXTENDED, /* fully TOASTable */
1341  -1, /* typmod */
1342  0, /* array dimensions for typBaseType */
1343  false, /* Type NOT NULL */
1344  InvalidOid); /* rowtypes never have a collation */
1345 
1346  pfree(relarrayname);
1347  }
1348 
1349  /*
1350  * now create an entry in pg_class for the relation.
1351  *
1352  * NOTE: we could get a unique-index failure here, in case someone else is
1353  * creating the same relation name in parallel but hadn't committed yet
1354  * when we checked for a duplicate name above.
1355  */
1356  AddNewRelationTuple(pg_class_desc,
1357  new_rel_desc,
1358  relid,
1359  new_type_oid,
1360  reloftypeid,
1361  ownerid,
1362  relkind,
1363  relfrozenxid,
1364  relminmxid,
1365  PointerGetDatum(relacl),
1366  reloptions);
1367 
1368  /*
1369  * now add tuples to pg_attribute for the attributes in our new relation.
1370  */
1371  AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind);
1372 
1373  /*
1374  * Make a dependency link to force the relation to be deleted if its
1375  * namespace is. Also make a dependency link to its owner, as well as
1376  * dependencies for any roles mentioned in the default ACL.
1377  *
1378  * For composite types, these dependencies are tracked for the pg_type
1379  * entry, so we needn't record them here. Likewise, TOAST tables don't
1380  * need a namespace dependency (they live in a pinned namespace) nor an
1381  * owner dependency (they depend indirectly through the parent table), nor
1382  * should they have any ACL entries. The same applies for extension
1383  * dependencies.
1384  *
1385  * Also, skip this in bootstrap mode, since we don't make dependencies
1386  * while bootstrapping.
1387  */
1388  if (relkind != RELKIND_COMPOSITE_TYPE &&
1389  relkind != RELKIND_TOASTVALUE &&
1391  {
1392  ObjectAddress myself,
1393  referenced;
1394 
1395  myself.classId = RelationRelationId;
1396  myself.objectId = relid;
1397  myself.objectSubId = 0;
1398 
1399  referenced.classId = NamespaceRelationId;
1400  referenced.objectId = relnamespace;
1401  referenced.objectSubId = 0;
1402  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1403 
1404  recordDependencyOnOwner(RelationRelationId, relid, ownerid);
1405 
1406  recordDependencyOnNewAcl(RelationRelationId, relid, 0, ownerid, relacl);
1407 
1408  recordDependencyOnCurrentExtension(&myself, false);
1409 
1410  if (reloftypeid)
1411  {
1412  referenced.classId = TypeRelationId;
1413  referenced.objectId = reloftypeid;
1414  referenced.objectSubId = 0;
1415  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1416  }
1417 
1418  /*
1419  * Make a dependency link to force the relation to be deleted if its
1420  * access method is. Do this only for relation and materialized views.
1421  *
1422  * No need to add an explicit dependency for the toast table, as the
1423  * main table depends on it.
1424  */
1425  if (relkind == RELKIND_RELATION ||
1426  relkind == RELKIND_MATVIEW)
1427  {
1428  referenced.classId = AccessMethodRelationId;
1429  referenced.objectId = accessmtd;
1430  referenced.objectSubId = 0;
1431  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1432  }
1433  }
1434 
1435  /* Post creation hook for new relation */
1436  InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
1437 
1438  /*
1439  * Store any supplied constraints and defaults.
1440  *
1441  * NB: this may do a CommandCounterIncrement and rebuild the relcache
1442  * entry, so the relation must be valid and self-consistent at this point.
1443  * In particular, there are not yet constraints and defaults anywhere.
1444  */
1445  StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
1446 
1447  /*
1448  * If there's a special on-commit action, remember it
1449  */
1450  if (oncommit != ONCOMMIT_NOOP)
1451  register_on_commit_action(relid, oncommit);
1452 
1453  /*
1454  * ok, the relation has been cataloged, so close our relations and return
1455  * the OID of the newly created relation.
1456  */
1457  table_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
1458  table_close(pg_class_desc, RowExclusiveLock);
1459 
1460  return relid;
1461 }
void register_on_commit_action(Oid relid, OnCommitAction action)
Definition: tablecmds.c:15239
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:810
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:513
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:787
#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:644
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:1748
#define NoLock
Definition: lockdefs.h:34
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:871
#define IsNormalProcessingMode()
Definition: miscadmin.h:394
bool IsUnderPostmaster
Definition: globals.c:109
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
static ObjectAddress AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, Oid ownerid, Oid new_row_type, Oid new_array_type)
Definition: heap.c:1024
static void StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
Definition: heap.c:2453
#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:523
#define Assert(condition)
Definition: c.h:738
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:2021
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition: aclchk.c:5499
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:392
#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:955
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:5423

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

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

1855 {
1856  Relation rel;
1857  HeapTuple tuple;
1858  Oid parentOid = InvalidOid,
1859  defaultPartOid = InvalidOid;
1860 
1861  /*
1862  * To drop a partition safely, we must grab exclusive lock on its parent,
1863  * because another backend might be about to execute a query on the parent
1864  * table. If it relies on previously cached partition descriptor, then it
1865  * could attempt to access the just-dropped relation as its partition. We
1866  * must therefore take a table lock strong enough to prevent all queries
1867  * on the table from proceeding until we commit and send out a
1868  * shared-cache-inval notice that will make them update their partition
1869  * descriptors.
1870  */
1871  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1872  if (!HeapTupleIsValid(tuple))
1873  elog(ERROR, "cache lookup failed for relation %u", relid);
1874  if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
1875  {
1876  parentOid = get_partition_parent(relid);
1878 
1879  /*
1880  * If this is not the default partition, dropping it will change the
1881  * default partition's partition constraint, so we must lock it.
1882  */
1883  defaultPartOid = get_default_partition_oid(parentOid);
1884  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1885  LockRelationOid(defaultPartOid, AccessExclusiveLock);
1886  }
1887 
1888  ReleaseSysCache(tuple);
1889 
1890  /*
1891  * Open and lock the relation.
1892  */
1893  rel = relation_open(relid, AccessExclusiveLock);
1894 
1895  /*
1896  * There can no longer be anyone *else* touching the relation, but we
1897  * might still have open queries or cursors, or pending trigger events, in
1898  * our own session.
1899  */
1900  CheckTableNotInUse(rel, "DROP TABLE");
1901 
1902  /*
1903  * This effectively deletes all rows in the table, and may be done in a
1904  * serializable transaction. In that case we must record a rw-conflict in
1905  * to this transaction from each transaction holding a predicate lock on
1906  * the table.
1907  */
1909 
1910  /*
1911  * Delete pg_foreign_table tuple first.
1912  */
1913  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1914  {
1915  Relation rel;
1916  HeapTuple tuple;
1917 
1918  rel = table_open(ForeignTableRelationId, RowExclusiveLock);
1919 
1921  if (!HeapTupleIsValid(tuple))
1922  elog(ERROR, "cache lookup failed for foreign table %u", relid);
1923 
1924  CatalogTupleDelete(rel, &tuple->t_self);
1925 
1926  ReleaseSysCache(tuple);
1928  }
1929 
1930  /*
1931  * If a partitioned table, delete the pg_partitioned_table tuple.
1932  */
1933  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1935 
1936  /*
1937  * If the relation being dropped is the default partition itself,
1938  * invalidate its entry in pg_partitioned_table.
1939  */
1940  if (relid == defaultPartOid)
1942 
1943  /*
1944  * Schedule unlinking of the relation's physical files at commit.
1945  */
1946  if (rel->rd_rel->relkind != RELKIND_VIEW &&
1947  rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
1948  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1949  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1950  {
1951  RelationDropStorage(rel);
1952  }
1953 
1954  /*
1955  * Close relcache entry, but *keep* AccessExclusiveLock on the relation
1956  * until transaction commit. This ensures no one else will try to do
1957  * something with the doomed relation.
1958  */
1959  relation_close(rel, NoLock);
1960 
1961  /*
1962  * Remove any associated relation synchronization states.
1963  */
1965 
1966  /*
1967  * Forget any ON COMMIT action for the rel
1968  */
1969  remove_on_commit_action(relid);
1970 
1971  /*
1972  * Flush the relation from the relcache. We want to do this before
1973  * starting to remove catalog entries, just to be certain that no relcache
1974  * entry rebuild will happen partway through. (That should not really
1975  * matter, since we don't do CommandCounterIncrement here, but let's be
1976  * safe.)
1977  */
1978  RelationForgetRelation(relid);
1979 
1980  /*
1981  * remove inheritance information
1982  */
1984 
1985  /*
1986  * delete statistics
1987  */
1988  RemoveStatistics(relid, 0);
1989 
1990  /*
1991  * delete attribute tuples
1992  */
1993  DeleteAttributeTuples(relid);
1994 
1995  /*
1996  * delete relation tuple
1997  */
1998  DeleteRelationTuple(relid);
1999 
2000  if (OidIsValid(parentOid))
2001  {
2002  /*
2003  * If this is not the default partition, the partition constraint of
2004  * the default partition has changed to include the portion of the key
2005  * space previously covered by the dropped partition.
2006  */
2007  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
2008  CacheInvalidateRelcacheByRelid(defaultPartOid);
2009 
2010  /*
2011  * Invalidate the parent's relcache so that the partition is no longer
2012  * included in its partition descriptor.
2013  */
2014  CacheInvalidateRelcacheByRelid(parentOid);
2015  /* keep the lock */
2016  }
2017 }
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:15275
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2736
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
Oid get_partition_parent(Oid relid)
Definition: partition.c:50
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1329
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:1506
#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:1473
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4457
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1535
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:3123
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define AccessExclusiveLock
Definition: lockdefs.h:45
void RemovePartitionKeyByRelId(Oid relid)
Definition: heap.c:3658
#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 3218 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().

3219 {
3220  List *relations = NIL;
3221  ListCell *cell;
3222 
3223  /* Open relations for processing, and grab exclusive access on each */
3224  foreach(cell, relids)
3225  {
3226  Oid rid = lfirst_oid(cell);
3227  Relation rel;
3228 
3229  rel = table_open(rid, AccessExclusiveLock);
3230  relations = lappend(relations, rel);
3231  }
3232 
3233  /* Don't allow truncate on tables that are referenced by foreign keys */
3234  heap_truncate_check_FKs(relations, true);
3235 
3236  /* OK to do it */
3237  foreach(cell, relations)
3238  {
3239  Relation rel = lfirst(cell);
3240 
3241  /* Truncate the relation */
3242  heap_truncate_one_rel(rel);
3243 
3244  /* Close the relation, but keep exclusive lock on it until commit */
3245  table_close(rel, NoLock);
3246  }
3247 }
#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:3259
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3303
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 3303 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().

3304 {
3305  List *oids = NIL;
3306  List *dependents;
3307  ListCell *cell;
3308 
3309  /*
3310  * Build a list of OIDs of the interesting relations.
3311  *
3312  * If a relation has no triggers, then it can neither have FKs nor be
3313  * referenced by a FK from another table, so we can ignore it. For
3314  * partitioned tables, FKs have no triggers, so we must include them
3315  * anyway.
3316  */
3317  foreach(cell, relations)
3318  {
3319  Relation rel = lfirst(cell);
3320 
3321  if (rel->rd_rel->relhastriggers ||
3322  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3323  oids = lappend_oid(oids, RelationGetRelid(rel));
3324  }
3325 
3326  /*
3327  * Fast path: if no relation has triggers, none has FKs either.
3328  */
3329  if (oids == NIL)
3330  return;
3331 
3332  /*
3333  * Otherwise, must scan pg_constraint. We make one pass with all the
3334  * relations considered; if this finds nothing, then all is well.
3335  */
3336  dependents = heap_truncate_find_FKs(oids);
3337  if (dependents == NIL)
3338  return;
3339 
3340  /*
3341  * Otherwise we repeat the scan once per relation to identify a particular
3342  * pair of relations to complain about. This is pretty slow, but
3343  * performance shouldn't matter much in a failure path. The reason for
3344  * doing things this way is to ensure that the message produced is not
3345  * dependent on chance row locations within pg_constraint.
3346  */
3347  foreach(cell, oids)
3348  {
3349  Oid relid = lfirst_oid(cell);
3350  ListCell *cell2;
3351 
3352  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
3353 
3354  foreach(cell2, dependents)
3355  {
3356  Oid relid2 = lfirst_oid(cell2);
3357 
3358  if (!list_member_oid(oids, relid2))
3359  {
3360  char *relname = get_rel_name(relid);
3361  char *relname2 = get_rel_name(relid2);
3362 
3363  if (tempTables)
3364  ereport(ERROR,
3365  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3366  errmsg("unsupported ON COMMIT and foreign key combination"),
3367  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3368  relname2, relname)));
3369  else
3370  ereport(ERROR,
3371  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3372  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3373  errdetail("Table \"%s\" references \"%s\".",
3374  relname2, relname),
3375  errhint("Truncate table \"%s\" at the same time, "
3376  "or use TRUNCATE ... CASCADE.",
3377  relname2)));
3378  }
3379  }
3380  }
3381 }
#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:1791
#define RelationGetRelid(relation)
Definition: rel.h:456
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3398
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

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

3399 {
3400  List *result = NIL;
3401  List *oids = list_copy(relationIds);
3402  List *parent_cons;
3403  ListCell *cell;
3404  ScanKeyData key;
3405  Relation fkeyRel;
3406  SysScanDesc fkeyScan;
3407  HeapTuple tuple;
3408  bool restart;
3409 
3410  oids = list_copy(relationIds);
3411 
3412  /*
3413  * Must scan pg_constraint. Right now, it is a seqscan because there is
3414  * no available index on confrelid.
3415  */
3416  fkeyRel = table_open(ConstraintRelationId, AccessShareLock);
3417 
3418 restart:
3419  restart = false;
3420  parent_cons = NIL;
3421 
3422  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3423  NULL, 0, NULL);
3424 
3425  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3426  {
3428 
3429  /* Not a foreign key */
3430  if (con->contype != CONSTRAINT_FOREIGN)
3431  continue;
3432 
3433  /* Not referencing one of our list of tables */
3434  if (!list_member_oid(oids, con->confrelid))
3435  continue;
3436 
3437  /*
3438  * If this constraint has a parent constraint which we have not seen
3439  * yet, keep track of it for the second loop, below. Tracking parent
3440  * constraints allows us to climb up to the top-level level constraint
3441  * and look for all possible relations referencing the partitioned
3442  * table.
3443  */
3444  if (OidIsValid(con->conparentid) &&
3445  !list_member_oid(parent_cons, con->conparentid))
3446  parent_cons = lappend_oid(parent_cons, con->conparentid);
3447 
3448  /*
3449  * Add referencer to result, unless present in input list. (Don't
3450  * worry about dupes: we'll fix that below).
3451  */
3452  if (!list_member_oid(relationIds, con->conrelid))
3453  result = lappend_oid(result, con->conrelid);
3454  }
3455 
3456  systable_endscan(fkeyScan);
3457 
3458  /*
3459  * Process each parent constraint we found to add the list of referenced
3460  * relations by them to the oids list. If we do add any new such
3461  * relations, redo the first loop above. Also, if we see that the parent
3462  * constraint in turn has a parent, add that so that we process all
3463  * relations in a single additional pass.
3464  */
3465  foreach(cell, parent_cons)
3466  {
3467  Oid parent = lfirst_oid(cell);
3468 
3469  ScanKeyInit(&key,
3470  Anum_pg_constraint_oid,
3471  BTEqualStrategyNumber, F_OIDEQ,
3472  ObjectIdGetDatum(parent));
3473 
3474  fkeyScan = systable_beginscan(fkeyRel, ConstraintOidIndexId,
3475  true, NULL, 1, &key);
3476 
3477  tuple = systable_getnext(fkeyScan);
3478  if (HeapTupleIsValid(tuple))
3479  {
3481 
3482  /*
3483  * pg_constraint rows always appear for partitioned hierarchies
3484  * this way: on the each side of the constraint, one row appears
3485  * for each partition that points to the top-most table on the
3486  * other side.
3487  *
3488  * Because of this arrangement, we can correctly catch all
3489  * relevant relations by adding to 'parent_cons' all rows with
3490  * valid conparentid, and to the 'oids' list all rows with a zero
3491  * conparentid. If any oids are added to 'oids', redo the first
3492  * loop above by setting 'restart'.
3493  */
3494  if (OidIsValid(con->conparentid))
3495  parent_cons = list_append_unique_oid(parent_cons,
3496  con->conparentid);
3497  else if (!list_member_oid(oids, con->confrelid))
3498  {
3499  oids = lappend_oid(oids, con->confrelid);
3500  restart = true;
3501  }
3502  }
3503 
3504  systable_endscan(fkeyScan);
3505  }
3506 
3507  list_free(parent_cons);
3508  if (restart)
3509  goto restart;
3510 
3511  table_close(fkeyRel, AccessShareLock);
3512  list_free(oids);
3513 
3514  /* Now sort and de-duplicate the result list */
3515  list_sort(result, list_oid_cmp);
3516  list_deduplicate_oid(result);
3517 
3518  return result;
3519 }
#define ConstraintOidIndexId
Definition: indexing.h:132
#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:644
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 3259 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().

3260 {
3261  Oid toastrelid;
3262 
3263  /*
3264  * Truncate the relation. Partitioned tables have no storage, so there is
3265  * nothing to do for them here.
3266  */
3267  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3268  return;
3269 
3270  /* Truncate the underlying relation */
3272 
3273  /* If the relation has indexes, truncate the indexes too */
3275 
3276  /* If there is a toast table, truncate that too */
3277  toastrelid = rel->rd_rel->reltoastrelid;
3278  if (OidIsValid(toastrelid))
3279  {
3280  Relation toastrel = table_open(toastrelid, AccessExclusiveLock);
3281 
3283  RelationTruncateIndexes(toastrel);
3284  /* keep the lock... */
3285  table_close(toastrel, NoLock);
3286  }
3287 }
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:644
static void table_relation_nontransactional_truncate(Relation rel)
Definition: tableam.h:1386
#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:3170

◆ InsertPgAttributeTuple()

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

Definition at line 726 of file heap.c.

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

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

730 {
731  Datum values[Natts_pg_attribute];
732  bool nulls[Natts_pg_attribute];
733  HeapTuple tup;
734 
735  /* This is a tad tedious, but way cleaner than what we used to do... */
736  memset(values, 0, sizeof(values));
737  memset(nulls, false, sizeof(nulls));
738 
739  values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
740  values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
741  values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
742  values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
743  values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
744  values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
745  values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
746  values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
747  values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
748  values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
749  values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
750  values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
751  values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
752  values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
753  values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(new_attribute->atthasmissing);
754  values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
755  values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(new_attribute->attgenerated);
756  values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
757  values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
758  values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
759  values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
760  values[Anum_pg_attribute_attoptions - 1] = attoptions;
761 
762  /* start out with empty permissions and empty options */
763  nulls[Anum_pg_attribute_attacl - 1] = true;
764  nulls[Anum_pg_attribute_attoptions - 1] = attoptions == (Datum) 0;
765  nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
766  nulls[Anum_pg_attribute_attmissingval - 1] = true;
767 
768  tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
769 
770  /* finally insert the new tuple, update the indexes, and clean up */
771  if (indstate != NULL)
772  CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
773  else
774  CatalogTupleInsert(pg_attribute_rel, tup);
775 
776  heap_freetuple(tup);
777 }
#define NameGetDatum(X)
Definition: postgres.h:595
#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
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
uintptr_t Datum
Definition: postgres.h:367
void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:204
#define BoolGetDatum(X)
Definition: postgres.h:402
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define Int32GetDatum(X)
Definition: postgres.h:479
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:183

◆ InsertPgClassTuple()

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

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

887 {
888  Form_pg_class rd_rel = new_rel_desc->rd_rel;
889  Datum values[Natts_pg_class];
890  bool nulls[Natts_pg_class];
891  HeapTuple tup;
892 
893  /* This is a tad tedious, but way cleaner than what we used to do... */
894  memset(values, 0, sizeof(values));
895  memset(nulls, false, sizeof(nulls));
896 
897  values[Anum_pg_class_oid - 1] = ObjectIdGetDatum(new_rel_oid);
898  values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
899  values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
900  values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
901  values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
902  values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
903  values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
904  values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
905  values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
906  values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
907  values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
908  values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
909  values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
910  values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
911  values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
912  values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
913  values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
914  values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
915  values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
916  values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
917  values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
918  values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
919  values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
920  values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
921  values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
922  values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
923  values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
924  values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite);
925  values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
926  values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
927  if (relacl != (Datum) 0)
928  values[Anum_pg_class_relacl - 1] = relacl;
929  else
930  nulls[Anum_pg_class_relacl - 1] = true;
931  if (reloptions != (Datum) 0)
932  values[Anum_pg_class_reloptions - 1] = reloptions;
933  else
934  nulls[Anum_pg_class_reloptions - 1] = true;
935 
936  /* relpartbound is set by updating this tuple, if necessary */
937  nulls[Anum_pg_class_relpartbound - 1] = true;
938 
939  tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
940 
941  /* finally insert the new tuple, update the indexes, and clean up */
942  CatalogTupleInsert(pg_class_desc, tup);
943 
944  heap_freetuple(tup);
945 }
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:183

◆ RelationClearMissing()

void RelationClearMissing ( Relation  rel)

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

2032 {
2033  Relation attr_rel;
2034  Oid relid = RelationGetRelid(rel);
2035  int natts = RelationGetNumberOfAttributes(rel);
2036  int attnum;
2037  Datum repl_val[Natts_pg_attribute];
2038  bool repl_null[Natts_pg_attribute];
2039  bool repl_repl[Natts_pg_attribute];
2040  Form_pg_attribute attrtuple;
2041  HeapTuple tuple,
2042  newtuple;
2043 
2044  memset(repl_val, 0, sizeof(repl_val));
2045  memset(repl_null, false, sizeof(repl_null));
2046  memset(repl_repl, false, sizeof(repl_repl));
2047 
2048  repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
2049  repl_null[Anum_pg_attribute_attmissingval - 1] = true;
2050 
2051  repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
2052  repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
2053 
2054 
2055  /* Get a lock on pg_attribute */
2056  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
2057 
2058  /* process each non-system attribute, including any dropped columns */
2059  for (attnum = 1; attnum <= natts; attnum++)
2060  {
2061  tuple = SearchSysCache2(ATTNUM,
2062  ObjectIdGetDatum(relid),
2063  Int16GetDatum(attnum));
2064  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
2065  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2066  attnum, relid);
2067 
2068  attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
2069 
2070  /* ignore any where atthasmissing is not true */
2071  if (attrtuple->atthasmissing)
2072  {
2073  newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
2074  repl_val, repl_null, repl_repl);
2075 
2076  CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
2077 
2078  heap_freetuple(newtuple);
2079  }
2080 
2081  ReleaseSysCache(tuple);
2082  }
2083 
2084  /*
2085  * Our update of the pg_attribute rows will force a relcache rebuild, so
2086  * there's nothing else to do here.
2087  */
2088  table_close(attr_rel, RowExclusiveLock);
2089 }
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:224
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 1726 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().

1728 {
1729  Relation attrdef_rel;
1730  ScanKeyData scankeys[2];
1731  SysScanDesc scan;
1732  HeapTuple tuple;
1733  bool found = false;
1734 
1735  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1736 
1737  ScanKeyInit(&scankeys[0],
1738  Anum_pg_attrdef_adrelid,
1739  BTEqualStrategyNumber, F_OIDEQ,
1740  ObjectIdGetDatum(relid));
1741  ScanKeyInit(&scankeys[1],
1742  Anum_pg_attrdef_adnum,
1743  BTEqualStrategyNumber, F_INT2EQ,
1745 
1746  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1747  NULL, 2, scankeys);
1748 
1749  /* There should be at most one matching tuple, but we loop anyway */
1750  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1751  {
1752  ObjectAddress object;
1753  Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
1754 
1755  object.classId = AttrDefaultRelationId;
1756  object.objectId = attrtuple->oid;
1757  object.objectSubId = 0;
1758 
1759  performDeletion(&object, behavior,
1760  internal ? PERFORM_DELETION_INTERNAL : 0);
1761 
1762  found = true;
1763  }
1764 
1765  systable_endscan(scan);
1766  table_close(attrdef_rel, RowExclusiveLock);
1767 
1768  if (complain && !found)
1769  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1770  relid, attnum);
1771 }
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:89
#define RowExclusiveLock
Definition: lockdefs.h:38
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:314
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 1781 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().

1782 {
1783  Relation attrdef_rel;
1784  Relation attr_rel;
1785  Relation myrel;
1786  ScanKeyData scankeys[1];
1787  SysScanDesc scan;
1788  HeapTuple tuple;
1789  Oid myrelid;
1790  AttrNumber myattnum;
1791 
1792  /* Grab an appropriate lock on the pg_attrdef relation */
1793  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1794 
1795  /* Find the pg_attrdef tuple */
1796  ScanKeyInit(&scankeys[0],
1797  Anum_pg_attrdef_oid,
1798  BTEqualStrategyNumber, F_OIDEQ,
1799  ObjectIdGetDatum(attrdefId));
1800 
1801  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1802  NULL, 1, scankeys);
1803 
1804  tuple = systable_getnext(scan);
1805  if (!HeapTupleIsValid(tuple))
1806  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1807 
1808  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1809  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1810 
1811  /* Get an exclusive lock on the relation owning the attribute */
1812  myrel = relation_open(myrelid, AccessExclusiveLock);
1813 
1814  /* Now we can delete the pg_attrdef row */
1815  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1816 
1817  systable_endscan(scan);
1818  table_close(attrdef_rel, RowExclusiveLock);
1819 
1820  /* Fix the pg_attribute row */
1821  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1822 
1823  tuple = SearchSysCacheCopy2(ATTNUM,
1824  ObjectIdGetDatum(myrelid),
1825  Int16GetDatum(myattnum));
1826  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1827  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1828  myattnum, myrelid);
1829 
1830  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1831 
1832  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1833 
1834  /*
1835  * Our update of the pg_attribute row will force a relcache rebuild, so
1836  * there's nothing else to do here.
1837  */
1838  table_close(attr_rel, RowExclusiveLock);
1839 
1840  /* Keep lock on attribute's rel until end of xact */
1841  relation_close(myrel, NoLock);
1842 }
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:91
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c: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:224
#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 1613 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().

1614 {
1615  Relation rel;
1616  Relation attr_rel;
1617  HeapTuple tuple;
1618  Form_pg_attribute attStruct;
1619  char newattname[NAMEDATALEN];
1620 
1621  /*
1622  * Grab an exclusive lock on the target table, which we will NOT release
1623  * until end of transaction. (In the simple case where we are directly
1624  * dropping this column, ATExecDropColumn already did this ... but when
1625  * cascading from a drop of some other object, we may not have any lock.)
1626  */
1627  rel = relation_open(relid, AccessExclusiveLock);
1628 
1629  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1630 
1631  tuple = SearchSysCacheCopy2(ATTNUM,
1632  ObjectIdGetDatum(relid),
1634  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1635  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1636  attnum, relid);
1637  attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
1638 
1639  if (attnum < 0)
1640  {
1641  /* System attribute (probably OID) ... just delete the row */
1642 
1643  CatalogTupleDelete(attr_rel, &tuple->t_self);
1644  }
1645  else
1646  {
1647  /* Dropping user attributes is lots harder */
1648 
1649  /* Mark the attribute as dropped */
1650  attStruct->attisdropped = true;
1651 
1652  /*
1653  * Set the type OID to invalid. A dropped attribute's type link
1654  * cannot be relied on (once the attribute is dropped, the type might
1655  * be too). Fortunately we do not need the type row --- the only
1656  * really essential information is the type's typlen and typalign,
1657  * which are preserved in the attribute's attlen and attalign. We set
1658  * atttypid to zero here as a means of catching code that incorrectly
1659  * expects it to be valid.
1660  */
1661  attStruct->atttypid = InvalidOid;
1662 
1663  /* Remove any NOT NULL constraint the column may have */
1664  attStruct->attnotnull = false;
1665 
1666  /* We don't want to keep stats for it anymore */
1667  attStruct->attstattarget = 0;
1668 
1669  /* Unset this so no one tries to look up the generation expression */
1670  attStruct->attgenerated = '\0';
1671 
1672  /*
1673  * Change the column name to something that isn't likely to conflict
1674  */
1675  snprintf(newattname, sizeof(newattname),
1676  "........pg.dropped.%d........", attnum);
1677  namestrcpy(&(attStruct->attname), newattname);
1678 
1679  /* clear the missing value if any */
1680  if (attStruct->atthasmissing)
1681  {
1682  Datum valuesAtt[Natts_pg_attribute];
1683  bool nullsAtt[Natts_pg_attribute];
1684  bool replacesAtt[Natts_pg_attribute];
1685 
1686  /* update the tuple - set atthasmissing and attmissingval */
1687  MemSet(valuesAtt, 0, sizeof(valuesAtt));
1688  MemSet(nullsAtt, false, sizeof(nullsAtt));
1689  MemSet(replacesAtt, false, sizeof(replacesAtt));
1690 
1691  valuesAtt[Anum_pg_attribute_atthasmissing - 1] =
1692  BoolGetDatum(false);
1693  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
1694  valuesAtt[Anum_pg_attribute_attmissingval - 1] = (Datum) 0;
1695  nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
1696  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
1697 
1698  tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
1699  valuesAtt, nullsAtt, replacesAtt);
1700  }
1701 
1702  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1703  }
1704 
1705  /*
1706  * Because updating the pg_attribute row will trigger a relcache flush for
1707  * the target relation, we need not do anything else to notify other
1708  * backends of the change.
1709  */
1710 
1711  table_close(attr_rel, RowExclusiveLock);
1712 
1713  if (attnum > 0)
1714  RemoveStatistics(relid, attnum);
1715 
1716  relation_close(rel, NoLock);
1717 }
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:971
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
int namestrcpy(Name name, const char *str)
Definition: name.c:250
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h: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:224
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:3123
#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 3658 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().

3659 {
3660  Relation rel;
3661  HeapTuple tuple;
3662 
3663  rel = table_open(PartitionedRelationId, RowExclusiveLock);
3664 
3665  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3666  if (!HeapTupleIsValid(tuple))
3667  elog(ERROR, "cache lookup failed for partition key of relation %u",
3668  relid);
3669 
3670  CatalogTupleDelete(rel, &tuple->t_self);
3671 
3672  ReleaseSysCache(tuple);
3674 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:269
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:214
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

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

3124 {
3125  Relation pgstatistic;
3126  SysScanDesc scan;
3127  ScanKeyData key[2];
3128  int nkeys;
3129  HeapTuple tuple;
3130 
3131  pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
3132 
3133  ScanKeyInit(&key[0],
3134  Anum_pg_statistic_starelid,
3135  BTEqualStrategyNumber, F_OIDEQ,
3136  ObjectIdGetDatum(relid));
3137 
3138  if (attnum == 0)
3139  nkeys = 1;
3140  else
3141  {
3142  ScanKeyInit(&key[1],
3143  Anum_pg_statistic_staattnum,
3144  BTEqualStrategyNumber, F_INT2EQ,
3146  nkeys = 2;
3147  }
3148 
3149  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
3150  NULL, nkeys, key);
3151 
3152  /* we must loop even when attnum != 0, in case of inherited stats */
3153  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3154  CatalogTupleDelete(pgstatistic, &tuple->t_self);
3155 
3156  systable_endscan(scan);
3157 
3158  table_close(pgstatistic, RowExclusiveLock);
3159 }
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:269
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:228
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ SetAttrMissing()

void SetAttrMissing ( Oid  relid,
char *  attname,
char *  value 
)

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

2100 {
2101  Datum valuesAtt[Natts_pg_attribute];
2102  bool nullsAtt[Natts_pg_attribute];
2103  bool replacesAtt[Natts_pg_attribute];
2104  Datum missingval;
2105  Form_pg_attribute attStruct;
2106  Relation attrrel,
2107  tablerel;
2108  HeapTuple atttup,
2109  newtup;
2110 
2111  /* lock the table the attribute belongs to */
2112  tablerel = table_open(relid, AccessExclusiveLock);
2113 
2114  /* Lock the attribute row and get the data */
2115  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2116  atttup = SearchSysCacheAttName(relid, attname);
2117  if (!HeapTupleIsValid(atttup))
2118  elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2119  attname, relid);
2120  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2121 
2122  /* get an array value from the value string */
2123  missingval = OidFunctionCall3(F_ARRAY_IN,
2125  ObjectIdGetDatum(attStruct->atttypid),
2126  Int32GetDatum(attStruct->atttypmod));
2127 
2128  /* update the tuple - set atthasmissing and attmissingval */
2129  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2130  MemSet(nullsAtt, false, sizeof(nullsAtt));
2131  MemSet(replacesAtt, false, sizeof(replacesAtt));
2132 
2133  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
2134  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2135  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2136  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2137 
2138  newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2139  valuesAtt, nullsAtt, replacesAtt);
2140  CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
2141 
2142  /* clean up */
2143  ReleaseSysCache(atttup);
2144  table_close(attrrel, RowExclusiveLock);
2145  table_close(tablerel, AccessExclusiveLock);
2146 }
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:971
#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:224
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1257
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define Int32GetDatum(X)
Definition: postgres.h:479
#define elog(elevel,...)
Definition: elog.h: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 2160 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().

2162 {
2163  char *adbin;
2164  Relation adrel;
2165  HeapTuple tuple;
2166  Datum values[4];
2167  static bool nulls[4] = {false, false, false, false};
2168  Relation attrrel;
2169  HeapTuple atttup;
2170  Form_pg_attribute attStruct;
2171  char attgenerated;
2172  Oid attrdefOid;
2173  ObjectAddress colobject,
2174  defobject;
2175 
2176  adrel = table_open(AttrDefaultRelationId, RowExclusiveLock);
2177 
2178  /*
2179  * Flatten expression to string form for storage.
2180  */
2181  adbin = nodeToString(expr);
2182 
2183  /*
2184  * Make the pg_attrdef entry.
2185  */
2186  attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId,
2187  Anum_pg_attrdef_oid);
2188  values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid);
2189  values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
2190  values[Anum_pg_attrdef_adnum - 1] = attnum;
2191  values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
2192 
2193  tuple = heap_form_tuple(adrel->rd_att, values, nulls);
2194  CatalogTupleInsert(adrel, tuple);
2195 
2196  defobject.classId = AttrDefaultRelationId;
2197  defobject.objectId = attrdefOid;
2198  defobject.objectSubId = 0;
2199 
2200  table_close(adrel, RowExclusiveLock);
2201 
2202  /* now can free some of the stuff allocated above */
2203  pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
2204  heap_freetuple(tuple);
2205  pfree(adbin);
2206 
2207  /*
2208  * Update the pg_attribute entry for the column to show that a default
2209  * exists.
2210  */
2211  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2212  atttup = SearchSysCacheCopy2(ATTNUM,
2215  if (!HeapTupleIsValid(atttup))
2216  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2217  attnum, RelationGetRelid(rel));
2218  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2219  attgenerated = attStruct->attgenerated;
2220  if (!attStruct->atthasdef)
2221  {
2222  Form_pg_attribute defAttStruct;
2223 
2224  ExprState *exprState;
2225  Expr *expr2 = (Expr *) expr;
2226  EState *estate = NULL;
2227  ExprContext *econtext;
2228  Datum valuesAtt[Natts_pg_attribute];
2229  bool nullsAtt[Natts_pg_attribute];
2230  bool replacesAtt[Natts_pg_attribute];
2231  Datum missingval = (Datum) 0;
2232  bool missingIsNull = true;
2233 
2234  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2235  MemSet(nullsAtt, false, sizeof(nullsAtt));
2236  MemSet(replacesAtt, false, sizeof(replacesAtt));
2237  valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2238  replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2239 
2240  if (add_column_mode && !attgenerated)
2241  {
2242  expr2 = expression_planner(expr2);
2243  estate = CreateExecutorState();
2244  exprState = ExecPrepareExpr(expr2, estate);
2245  econtext = GetPerTupleExprContext(estate);
2246 
2247  missingval = ExecEvalExpr(exprState, econtext,
2248  &missingIsNull);
2249 
2250  FreeExecutorState(estate);
2251 
2252  defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1);
2253 
2254  if (missingIsNull)
2255  {
2256  /* if the default evaluates to NULL, just store a NULL array */
2257  missingval = (Datum) 0;
2258  }
2259  else
2260  {
2261  /* otherwise make a one-element array of the value */
2262  missingval = PointerGetDatum(construct_array(&missingval,
2263  1,
2264  defAttStruct->atttypid,
2265  defAttStruct->attlen,
2266  defAttStruct->attbyval,
2267  defAttStruct->attalign));
2268  }
2269 
2270  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
2271  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2272  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2273  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2274  nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull;
2275  }
2276  atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2277  valuesAtt, nullsAtt, replacesAtt);
2278 
2279  CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
2280 
2281  if (!missingIsNull)
2282  pfree(DatumGetPointer(missingval));
2283 
2284  }
2285  table_close(attrrel, RowExclusiveLock);
2286  heap_freetuple(atttup);
2287 
2288  /*
2289  * Make a dependency so that the pg_attrdef entry goes away if the column
2290  * (or whole table) is deleted.
2291  */
2292  colobject.classId = RelationRelationId;
2293  colobject.objectId = RelationGetRelid(rel);
2294  colobject.objectSubId = attnum;
2295 
2296  recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
2297 
2298  /*
2299  * Record dependencies on objects used in the expression, too.
2300  */
2301  if (attgenerated)
2302  {
2303  /*
2304  * Generated column: Dropping anything that the generation expression
2305  * refers to automatically drops the generated column.
2306  */
2307  recordDependencyOnSingleRelExpr(&colobject, expr, RelationGetRelid(rel),
2309  DEPENDENCY_AUTO, false);
2310  }
2311  else
2312  {
2313  /*
2314  * Normal default: Dropping anything that the default refers to
2315  * requires CASCADE and drops the default only.
2316  */
2317  recordDependencyOnSingleRelExpr(&defobject, expr, RelationGetRelid(rel),
2319  DEPENDENCY_NORMAL, false);
2320  }
2321 
2322  /*
2323  * Post creation hook for attribute defaults.
2324  *
2325  * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
2326  * couple of deletion/creation of the attribute's default entry, so the
2327  * callee should check existence of an older version of this entry if it
2328  * needs to distinguish.
2329  */
2330  InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
2331  RelationGetRelid(rel), attnum, is_internal);
2332 
2333  return attrdefOid;
2334 }
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:6157
#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:3292
#define AttrDefaultOidIndexId
Definition: indexing.h:91
#define MemSet(start, val, len)
Definition: c.h:971
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:1633
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define DatumGetPointer(X)
Definition: postgres.h:549
static Datum values[MAXATTR]
Definition: bootstrap.c:167
#define elog(elevel,...)
Definition: elog.h: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:183

◆ StorePartitionBound()

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

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

3690 {
3691  Relation classRel;
3692  HeapTuple tuple,
3693  newtuple;
3694  Datum new_val[Natts_pg_class];
3695  bool new_null[Natts_pg_class],
3696  new_repl[Natts_pg_class];
3697  Oid defaultPartOid;
3698 
3699  /* Update pg_class tuple */
3700  classRel = table_open(RelationRelationId, RowExclusiveLock);
3701  tuple = SearchSysCacheCopy1(RELOID,
3703  if (!HeapTupleIsValid(tuple))
3704  elog(ERROR, "cache lookup failed for relation %u",
3705  RelationGetRelid(rel));
3706 
3707 #ifdef USE_ASSERT_CHECKING
3708  {
3709  Form_pg_class classForm;
3710  bool isnull;
3711 
3712  classForm = (Form_pg_class) GETSTRUCT(tuple);
3713  Assert(!classForm->relispartition);
3714  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3715  &isnull);
3716  Assert(isnull);
3717  }
3718 #endif
3719 
3720  /* Fill in relpartbound value */
3721  memset(new_val, 0, sizeof(new_val));
3722  memset(new_null, false, sizeof(new_null));
3723  memset(new_repl, false, sizeof(new_repl));
3724  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3725  new_null[Anum_pg_class_relpartbound - 1] = false;
3726  new_repl[Anum_pg_class_relpartbound - 1] = true;
3727  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3728  new_val, new_null, new_repl);
3729  /* Also set the flag */
3730  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3731  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3732  heap_freetuple(newtuple);
3733  table_close(classRel, RowExclusiveLock);
3734 
3735  /*
3736  * If we're storing bounds for the default partition, update
3737  * pg_partitioned_table too.
3738  */
3739  if (bound->is_default)
3741  RelationGetRelid(rel));
3742 
3743  /* Make these updates visible */
3745 
3746  /*
3747  * The partition constraint for the default partition depends on the
3748  * partition bounds of every other partition, so we must invalidate the
3749  * relcache entry for that partition every time a partition is added or
3750  * removed.
3751  */
3752  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3753  if (OidIsValid(defaultPartOid))
3754  CacheInvalidateRelcacheByRelid(defaultPartOid);
3755 
3756  CacheInvalidateRelcache(parent);
3757 }
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:644
#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:1329
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1006
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:738
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
FormData_pg_class * Form_pg_class
Definition: pg_class.h: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 3526 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().

3533 {
3534  int i;
3535  int2vector *partattrs_vec;
3536  oidvector *partopclass_vec;
3537  oidvector *partcollation_vec;
3538  Datum partexprDatum;
3539  Relation pg_partitioned_table;
3540  HeapTuple tuple;
3541  Datum values[Natts_pg_partitioned_table];
3542  bool nulls[Natts_pg_partitioned_table];
3543  ObjectAddress myself;
3544  ObjectAddress referenced;
3545 
3546  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3547 
3548  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3549  partattrs_vec = buildint2vector(partattrs, partnatts);
3550  partopclass_vec = buildoidvector(partopclass, partnatts);
3551  partcollation_vec = buildoidvector(partcollation, partnatts);
3552 
3553  /* Convert the expressions (if any) to a text datum */
3554  if (partexprs)
3555  {
3556  char *exprString;
3557 
3558  exprString = nodeToString(partexprs);
3559  partexprDatum = CStringGetTextDatum(exprString);
3560  pfree(exprString);
3561  }
3562  else
3563  partexprDatum = (Datum) 0;
3564 
3565  pg_partitioned_table = table_open(PartitionedRelationId, RowExclusiveLock);
3566 
3567  MemSet(nulls, false, sizeof(nulls));
3568 
3569  /* Only this can ever be NULL */
3570  if (!partexprDatum)
3571  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3572 
3573  values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
3574  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3575  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3576  values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
3577  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3578  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3579  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3580  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3581 
3582  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3583 
3584  CatalogTupleInsert(pg_partitioned_table, tuple);
3585  table_close(pg_partitioned_table, RowExclusiveLock);
3586 
3587  /* Mark this relation as dependent on a few things as follows */
3588  myself.classId = RelationRelationId;
3589  myself.objectId = RelationGetRelid(rel);
3590  myself.objectSubId = 0;
3591 
3592  /* Operator class and collation per key column */
3593  for (i = 0; i < partnatts; i++)
3594  {
3595  referenced.classId = OperatorClassRelationId;
3596  referenced.objectId = partopclass[i];
3597  referenced.objectSubId = 0;
3598 
3599  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3600 
3601  /* The default collation is pinned, so don't bother recording it */
3602  if (OidIsValid(partcollation[i]) &&
3603  partcollation[i] != DEFAULT_COLLATION_OID)
3604  {
3605  referenced.classId = CollationRelationId;
3606  referenced.objectId = partcollation[i];
3607  referenced.objectSubId = 0;
3608 
3609  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3610  }
3611  }
3612 
3613  /*
3614  * The partitioning columns are made internally dependent on the table,
3615  * because we cannot drop any of them without dropping the whole table.
3616  * (ATExecDropColumn independently enforces that, but it's not bulletproof
3617  * so we need the dependencies too.)
3618  */
3619  for (i = 0; i < partnatts; i++)
3620  {
3621  if (partattrs[i] == 0)
3622  continue; /* ignore expressions here */
3623 
3624  referenced.classId = RelationRelationId;
3625  referenced.objectId = RelationGetRelid(rel);
3626  referenced.objectSubId = partattrs[i];
3627 
3628  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
3629  }
3630 
3631  /*
3632  * Also consider anything mentioned in partition expressions. External
3633  * references (e.g. functions) get NORMAL dependencies. Table columns
3634  * mentioned in the expressions are handled the same as plain partitioning
3635  * columns, i.e. they become internally dependent on the whole table.
3636  */
3637  if (partexprs)
3639  (Node *) partexprs,
3640  RelationGetRelid(rel),
3643  true /* reverse the self-deps */ );
3644 
3645  /*
3646  * We must invalidate the relcache so that the next
3647  * CommandCounterIncrement() will cause the same to be rebuilt using the
3648  * information in just created catalog entry.
3649  */
3651 }
Definition: c.h:594
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:971
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:644
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define RowExclusiveLock
Definition: lockdefs.h:38
Definition: c.h:583
uintptr_t Datum
Definition: postgres.h:367
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:738
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:1633
#define CharGetDatum(X)
Definition: postgres.h:416
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int i
#define CStringGetTextDatum(s)
Definition: builtins.h: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:183

◆ 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:668
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:615

◆ 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:668
#define ERROR
Definition: elog.h:43
static const FormData_pg_attribute * SysAtt[]
Definition: heap.c:241
#define elog(elevel,...)
Definition: elog.h:214