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, 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 2521 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().

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

◆ 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:608
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
Oid attcollation
Definition: pg_attribute.h:164
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
Definition: heap.c:261
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
Oid atttypid
Definition: pg_attribute.h:49
#define ereport(elevel, rest)
Definition: elog.h:141
#define MaxHeapAttributeNumber
Definition: htup_details.h:47
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
#define NameStr(name)
Definition: c.h: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:1069
#define RelationGetDescr(relation)
Definition: rel.h:454
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2526
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:608
char get_typtype(Oid typid)
Definition: lsyscache.c:2407
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:358
#define OidIsValid(objectId)
Definition: c.h:644
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2499
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
Oid attcollation
Definition: pg_attribute.h:164
List * list_delete_last(List *list)
Definition: list.c:878
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
Oid atttypid
Definition: pg_attribute.h:49
#define ereport(elevel, rest)
Definition: elog.h:141
Oid get_range_collation(Oid rangeOid)
Definition: lsyscache.c:3161
#define CHKATYPE_IS_PARTKEY
Definition: heap.h:25
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:675
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define CHKATYPE_ANYRECORD
Definition: heap.h:24
#define CHKATYPE_ANYARRAY
Definition: heap.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
#define NameStr(name)
Definition: c.h: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:2299
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:2848
Oid get_range_subtype(Oid rangeOid)
Definition: lsyscache.c:3135

◆ cookDefault()

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

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

3010 {
3011  Node *expr;
3012 
3013  Assert(raw_default != NULL);
3014 
3015  /*
3016  * Transform raw parsetree to executable expression.
3017  */
3018  expr = transformExpr(pstate, raw_default, attgenerated ? EXPR_KIND_GENERATED_COLUMN : EXPR_KIND_COLUMN_DEFAULT);
3019 
3020  if (attgenerated)
3021  {
3022  check_nested_generated(pstate, expr);
3023 
3024  if (contain_mutable_functions(expr))
3025  ereport(ERROR,
3026  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
3027  errmsg("generation expression is not immutable")));
3028  }
3029  else
3030  {
3031  /*
3032  * For a default expression, transformExpr() should have rejected
3033  * column references.
3034  */
3035  Assert(!contain_var_clause(expr));
3036  }
3037 
3038  /*
3039  * Coerce the expression to the correct type and typmod, if given. This
3040  * should match the parser's processing of non-defaulted expressions ---
3041  * see transformAssignedExpr().
3042  */
3043  if (OidIsValid(atttypid))
3044  {
3045  Oid type_id = exprType(expr);
3046 
3047  expr = coerce_to_target_type(pstate, expr, type_id,
3048  atttypid, atttypmod,
3051  -1);
3052  if (expr == NULL)
3053  ereport(ERROR,
3054  (errcode(ERRCODE_DATATYPE_MISMATCH),
3055  errmsg("column \"%s\" is of type %s"
3056  " but default expression is of type %s",
3057  attname,
3059  format_type_be(type_id)),
3060  errhint("You will need to rewrite or cast the expression.")));
3061  }
3062 
3063  /*
3064  * Finally, take care of collations in the finished expression.
3065  */
3066  assign_expr_collations(pstate, expr);
3067 
3068  return expr;
3069 }
int errhint(const char *fmt,...)
Definition: elog.c:1069
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:145
Definition: nodes.h:525
int errcode(int sqlerrcode)
Definition: elog.c:608
char * format_type_be(Oid type_oid)
Definition: format_type.c:326
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h: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:78
Oid atttypid
Definition: pg_attribute.h:49
#define ereport(elevel, rest)
Definition: elog.h:141
#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:2986
int errmsg(const char *fmt,...)
Definition: elog.c:822
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:647

◆ DeleteAttributeTuples()

void DeleteAttributeTuples ( Oid  relid)

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

1534 {
1535  Relation attrel;
1536  SysScanDesc scan;
1537  ScanKeyData key[1];
1538  HeapTuple atttup;
1539 
1540  /* Grab an appropriate lock on the pg_attribute relation */
1541  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1542 
1543  /* Use the index to scan only attributes of the target relation */
1544  ScanKeyInit(&key[0],
1545  Anum_pg_attribute_attrelid,
1546  BTEqualStrategyNumber, F_OIDEQ,
1547  ObjectIdGetDatum(relid));
1548 
1549  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1550  NULL, 1, key);
1551 
1552  /* Delete all the matching tuples */
1553  while ((atttup = systable_getnext(scan)) != NULL)
1554  CatalogTupleDelete(attrel, &atttup->t_self);
1555 
1556  /* Clean up after the scan */
1557  systable_endscan(scan);
1558  table_close(attrel, RowExclusiveLock);
1559 }
#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 1504 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().

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

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

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

1571 {
1572  Relation attrel;
1573  SysScanDesc scan;
1574  ScanKeyData key[2];
1575  HeapTuple atttup;
1576 
1577  /* Grab an appropriate lock on the pg_attribute relation */
1578  attrel = table_open(AttributeRelationId, RowExclusiveLock);
1579 
1580  /* Use the index to scan only system attributes of the target relation */
1581  ScanKeyInit(&key[0],
1582  Anum_pg_attribute_attrelid,
1583  BTEqualStrategyNumber, F_OIDEQ,
1584  ObjectIdGetDatum(relid));
1585  ScanKeyInit(&key[1],
1586  Anum_pg_attribute_attnum,
1587  BTLessEqualStrategyNumber, F_INT2LE,
1588  Int16GetDatum(0));
1589 
1590  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1591  NULL, 2, key);
1592 
1593  /* Delete all the matching tuples */
1594  while ((atttup = systable_getnext(scan)) != NULL)
1595  CatalogTupleDelete(attrel, &atttup->t_self);
1596 
1597  /* Clean up after the scan */
1598  systable_endscan(scan);
1599  table_close(attrel, RowExclusiveLock);
1600 }
#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:608
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:195
Form_pg_class rd_rel
Definition: rel.h:84
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:485
SMgrRelation RelationCreateStorage(RelFileNode rnode, char relpersistence)
Definition: storage.c:78
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
#define IsNormalProcessingMode()
Definition: miscadmin.h:374
int errdetail(const char *fmt,...)
Definition: elog.c:955
#define InvalidTransactionId
Definition: transam.h:31
#define ereport(elevel, rest)
Definition: elog.h:141
#define InvalidMultiXactId
Definition: multixact.h:23
#define InvalidOid
Definition: postgres_ext.h:36
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:1376
bool IsCatalogNamespace(Oid namespaceId)
Definition: catalog.c:177
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:3181

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

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

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

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

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

◆ heap_truncate()

void heap_truncate ( List relids)

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

3217 {
3218  List *relations = NIL;
3219  ListCell *cell;
3220 
3221  /* Open relations for processing, and grab exclusive access on each */
3222  foreach(cell, relids)
3223  {
3224  Oid rid = lfirst_oid(cell);
3225  Relation rel;
3226 
3227  rel = table_open(rid, AccessExclusiveLock);
3228  relations = lappend(relations, rel);
3229  }
3230 
3231  /* Don't allow truncate on tables that are referenced by foreign keys */
3232  heap_truncate_check_FKs(relations, true);
3233 
3234  /* OK to do it */
3235  foreach(cell, relations)
3236  {
3237  Relation rel = lfirst(cell);
3238 
3239  /* Truncate the relation */
3240  heap_truncate_one_rel(rel);
3241 
3242  /* Close the relation, but keep exclusive lock on it until commit */
3243  table_close(rel, NoLock);
3244  }
3245 }
#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:3257
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3301
unsigned int Oid
Definition: postgres_ext.h:31
#define NoLock
Definition: lockdefs.h:34
List * lappend(List *list, void *datum)
Definition: list.c:322
#define lfirst(lc)
Definition: pg_list.h:190
#define AccessExclusiveLock
Definition: lockdefs.h:45
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:192

◆ heap_truncate_check_FKs()

void heap_truncate_check_FKs ( List relations,
bool  tempTables 
)

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

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

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

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

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

3258 {
3259  Oid toastrelid;
3260 
3261  /*
3262  * Truncate the relation. Partitioned tables have no storage, so there is
3263  * nothing to do for them here.
3264  */
3265  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
3266  return;
3267 
3268  /* Truncate the underlying relation */
3270 
3271  /* If the relation has indexes, truncate the indexes too */
3273 
3274  /* If there is a toast table, truncate that too */
3275  toastrelid = rel->rd_rel->reltoastrelid;
3276  if (OidIsValid(toastrelid))
3277  {
3278  Relation toastrel = table_open(toastrelid, AccessExclusiveLock);
3279 
3281  RelationTruncateIndexes(toastrel);
3282  /* keep the lock... */
3283  table_close(toastrel, NoLock);
3284  }
3285 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
Form_pg_class rd_rel
Definition: rel.h:84
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:1393
#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:3168

◆ InsertPgAttributeTuple()

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

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

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

2030 {
2031  Relation attr_rel;
2032  Oid relid = RelationGetRelid(rel);
2033  int natts = RelationGetNumberOfAttributes(rel);
2034  int attnum;
2035  Datum repl_val[Natts_pg_attribute];
2036  bool repl_null[Natts_pg_attribute];
2037  bool repl_repl[Natts_pg_attribute];
2038  Form_pg_attribute attrtuple;
2039  HeapTuple tuple,
2040  newtuple;
2041 
2042  memset(repl_val, 0, sizeof(repl_val));
2043  memset(repl_null, false, sizeof(repl_null));
2044  memset(repl_repl, false, sizeof(repl_repl));
2045 
2046  repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
2047  repl_null[Anum_pg_attribute_attmissingval - 1] = true;
2048 
2049  repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
2050  repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
2051 
2052 
2053  /* Get a lock on pg_attribute */
2054  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
2055 
2056  /* process each non-system attribute, including any dropped columns */
2057  for (attnum = 1; attnum <= natts; attnum++)
2058  {
2059  tuple = SearchSysCache2(ATTNUM,
2060  ObjectIdGetDatum(relid),
2061  Int16GetDatum(attnum));
2062  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
2063  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2064  attnum, relid);
2065 
2066  attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
2067 
2068  /* ignore any where atthasmissing is not true */
2069  if (attrtuple->atthasmissing)
2070  {
2071  newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
2072  repl_val, repl_null, repl_repl);
2073 
2074  CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
2075 
2076  heap_freetuple(newtuple);
2077  }
2078 
2079  ReleaseSysCache(tuple);
2080  }
2081 
2082  /*
2083  * Our update of the pg_attribute rows will force a relcache rebuild, so
2084  * there's nothing else to do here.
2085  */
2086  table_close(attr_rel, RowExclusiveLock);
2087 }
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:454
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:434
#define Int16GetDatum(X)
Definition: postgres.h:451
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define BoolGetDatum(X)
Definition: postgres.h:402
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1127
#define elog(elevel,...)
Definition: elog.h:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define RelationGetRelid(relation)
Definition: rel.h:428

◆ RemoveAttrDefault()

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

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

1726 {
1727  Relation attrdef_rel;
1728  ScanKeyData scankeys[2];
1729  SysScanDesc scan;
1730  HeapTuple tuple;
1731  bool found = false;
1732 
1733  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1734 
1735  ScanKeyInit(&scankeys[0],
1736  Anum_pg_attrdef_adrelid,
1737  BTEqualStrategyNumber, F_OIDEQ,
1738  ObjectIdGetDatum(relid));
1739  ScanKeyInit(&scankeys[1],
1740  Anum_pg_attrdef_adnum,
1741  BTEqualStrategyNumber, F_INT2EQ,
1743 
1744  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1745  NULL, 2, scankeys);
1746 
1747  /* There should be at most one matching tuple, but we loop anyway */
1748  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1749  {
1750  ObjectAddress object;
1751  Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
1752 
1753  object.classId = AttrDefaultRelationId;
1754  object.objectId = attrtuple->oid;
1755  object.objectSubId = 0;
1756 
1757  performDeletion(&object, behavior,
1758  internal ? PERFORM_DELETION_INTERNAL : 0);
1759 
1760  found = true;
1761  }
1762 
1763  systable_endscan(scan);
1764  table_close(attrdef_rel, RowExclusiveLock);
1765 
1766  if (complain && !found)
1767  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1768  relid, attnum);
1769 }
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:315
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:134

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

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

1780 {
1781  Relation attrdef_rel;
1782  Relation attr_rel;
1783  Relation myrel;
1784  ScanKeyData scankeys[1];
1785  SysScanDesc scan;
1786  HeapTuple tuple;
1787  Oid myrelid;
1788  AttrNumber myattnum;
1789 
1790  /* Grab an appropriate lock on the pg_attrdef relation */
1791  attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1792 
1793  /* Find the pg_attrdef tuple */
1794  ScanKeyInit(&scankeys[0],
1795  Anum_pg_attrdef_oid,
1796  BTEqualStrategyNumber, F_OIDEQ,
1797  ObjectIdGetDatum(attrdefId));
1798 
1799  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1800  NULL, 1, scankeys);
1801 
1802  tuple = systable_getnext(scan);
1803  if (!HeapTupleIsValid(tuple))
1804  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1805 
1806  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1807  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1808 
1809  /* Get an exclusive lock on the relation owning the attribute */
1810  myrel = relation_open(myrelid, AccessExclusiveLock);
1811 
1812  /* Now we can delete the pg_attrdef row */
1813  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1814 
1815  systable_endscan(scan);
1816  table_close(attrdef_rel, RowExclusiveLock);
1817 
1818  /* Fix the pg_attribute row */
1819  attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1820 
1821  tuple = SearchSysCacheCopy2(ATTNUM,
1822  ObjectIdGetDatum(myrelid),
1823  Int16GetDatum(myattnum));
1824  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1825  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1826  myattnum, myrelid);
1827 
1828  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1829 
1830  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1831 
1832  /*
1833  * Our update of the pg_attribute row will force a relcache rebuild, so
1834  * there's nothing else to do here.
1835  */
1836  table_close(attr_rel, RowExclusiveLock);
1837 
1838  /* Keep lock on attribute's rel until end of xact */
1839  relation_close(myrel, NoLock);
1840 }
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:200
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define elog(elevel,...)
Definition: elog.h:228
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:176
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
int16 AttrNumber
Definition: attnum.h:21
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RemoveAttributeById()

void RemoveAttributeById ( Oid  relid,
AttrNumber  attnum 
)

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

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

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

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

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

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

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

3122 {
3123  Relation pgstatistic;
3124  SysScanDesc scan;
3125  ScanKeyData key[2];
3126  int nkeys;
3127  HeapTuple tuple;
3128 
3129  pgstatistic = table_open(StatisticRelationId, RowExclusiveLock);
3130 
3131  ScanKeyInit(&key[0],
3132  Anum_pg_statistic_starelid,
3133  BTEqualStrategyNumber, F_OIDEQ,
3134  ObjectIdGetDatum(relid));
3135 
3136  if (attnum == 0)
3137  nkeys = 1;
3138  else
3139  {
3140  ScanKeyInit(&key[1],
3141  Anum_pg_statistic_staattnum,
3142  BTEqualStrategyNumber, F_INT2EQ,
3144  nkeys = 2;
3145  }
3146 
3147  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
3148  NULL, nkeys, key);
3149 
3150  /* we must loop even when attnum != 0, in case of inherited stats */
3151  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3152  CatalogTupleDelete(pgstatistic, &tuple->t_self);
3153 
3154  systable_endscan(scan);
3155 
3156  table_close(pgstatistic, RowExclusiveLock);
3157 }
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 2097 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().

2098 {
2099  Datum valuesAtt[Natts_pg_attribute];
2100  bool nullsAtt[Natts_pg_attribute];
2101  bool replacesAtt[Natts_pg_attribute];
2102  Datum missingval;
2103  Form_pg_attribute attStruct;
2104  Relation attrrel,
2105  tablerel;
2106  HeapTuple atttup,
2107  newtup;
2108 
2109  /* lock the table the attribute belongs to */
2110  tablerel = table_open(relid, AccessExclusiveLock);
2111 
2112  /* Lock the attribute row and get the data */
2113  attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2114  atttup = SearchSysCacheAttName(relid, attname);
2115  if (!HeapTupleIsValid(atttup))
2116  elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2117  attname, relid);
2118  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2119 
2120  /* get an array value from the value string */
2121  missingval = OidFunctionCall3(F_ARRAY_IN,
2123  ObjectIdGetDatum(attStruct->atttypid),
2124  Int32GetDatum(attStruct->atttypmod));
2125 
2126  /* update the tuple - set atthasmissing and attmissingval */
2127  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2128  MemSet(nullsAtt, false, sizeof(nullsAtt));
2129  MemSet(replacesAtt, false, sizeof(replacesAtt));
2130 
2131  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
2132  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2133  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2134  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2135 
2136  newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2137  valuesAtt, nullsAtt, replacesAtt);
2138  CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
2139 
2140  /* clean up */
2141  ReleaseSysCache(atttup);
2142  table_close(attrrel, RowExclusiveLock);
2143  table_close(tablerel, AccessExclusiveLock);
2144 }
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:454
#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:200
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition: fmgr.h:657
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define BoolGetDatum(X)
Definition: postgres.h:402
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:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113

◆ StoreAttrDefault()

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

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

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

◆ StorePartitionBound()

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

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

3688 {
3689  Relation classRel;
3690  HeapTuple tuple,
3691  newtuple;
3692  Datum new_val[Natts_pg_class];
3693  bool new_null[Natts_pg_class],
3694  new_repl[Natts_pg_class];
3695  Oid defaultPartOid;
3696 
3697  /* Update pg_class tuple */
3698  classRel = table_open(RelationRelationId, RowExclusiveLock);
3699  tuple = SearchSysCacheCopy1(RELOID,
3701  if (!HeapTupleIsValid(tuple))
3702  elog(ERROR, "cache lookup failed for relation %u",
3703  RelationGetRelid(rel));
3704 
3705 #ifdef USE_ASSERT_CHECKING
3706  {
3707  Form_pg_class classForm;
3708  bool isnull;
3709 
3710  classForm = (Form_pg_class) GETSTRUCT(tuple);
3711  Assert(!classForm->relispartition);
3712  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3713  &isnull);
3714  Assert(isnull);
3715  }
3716 #endif
3717 
3718  /* Fill in relpartbound value */
3719  memset(new_val, 0, sizeof(new_val));
3720  memset(new_null, false, sizeof(new_null));
3721  memset(new_repl, false, sizeof(new_repl));
3722  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3723  new_null[Anum_pg_class_relpartbound - 1] = false;
3724  new_repl[Anum_pg_class_relpartbound - 1] = true;
3725  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3726  new_val, new_null, new_repl);
3727  /* Also set the flag */
3728  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3729  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3730  heap_freetuple(newtuple);
3731  table_close(classRel, RowExclusiveLock);
3732 
3733  /*
3734  * If we're storing bounds for the default partition, update
3735  * pg_partitioned_table too.
3736  */
3737  if (bound->is_default)
3739  RelationGetRelid(rel));
3740 
3741  /* Make these updates visible */
3743 
3744  /*
3745  * The partition constraint for the default partition depends on the
3746  * partition bounds of every other partition, so we must invalidate the
3747  * relcache entry for that partition every time a partition is added or
3748  * removed.
3749  */
3750  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3751  if (OidIsValid(defaultPartOid))
3752  CacheInvalidateRelcacheByRelid(defaultPartOid);
3753 
3754  CacheInvalidateRelcache(parent);
3755 }
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:454
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:1005
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h: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:228
#define CStringGetTextDatum(s)
Definition: builtins.h:87
char * nodeToString(const void *obj)
Definition: outfuncs.c:4328
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:428
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 3524 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().

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