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
 

Typedefs

typedef struct RawColumnDefault RawColumnDefault
 
typedef struct CookedConstraint CookedConstraint
 

Functions

Relation heap_create (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid relfilenode, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods)
 
Oid heap_create_with_catalog (const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid reltypeid, Oid reloftypeid, Oid ownerid, TupleDesc tupdesc, List *cooked_constraints, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool oidislocal, int oidinhcount, OnCommitAction oncommit, Datum reloptions, bool use_user_acl, bool allow_system_table_mods, bool is_internal, Oid relrewrite, ObjectAddress *typaddress)
 
void heap_create_init_fork (Relation rel)
 
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)
 
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)
 
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)
 
Form_pg_attribute SystemAttributeDefinition (AttrNumber attno, bool relhasoids)
 
Form_pg_attribute SystemAttributeByName (const char *attname, bool relhasoids)
 
void CheckAttributeNamesTypes (TupleDesc tupdesc, char relkind, bool allow_system_table_mods)
 
void CheckAttributeType (const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, bool allow_system_table_mods)
 
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)
 

Typedef Documentation

◆ CookedConstraint

◆ RawColumnDefault

Function Documentation

◆ AddRelationNewConstraints()

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

Definition at line 2459 of file heap.c.

References addRangeTableEntryForRelation(), addRTEtoQuery(), Assert, RawColumnDefault::attnum, CookedConstraint::attnum, ChooseConstraintName(), Constraint::conname, CookedConstraint::conoid, tupleDesc::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, 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, 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().

2465 {
2466  List *cookedConstraints = NIL;
2468  TupleConstr *oldconstr;
2469  int numoldchecks;
2470  ParseState *pstate;
2471  RangeTblEntry *rte;
2472  int numchecks;
2473  List *checknames;
2474  ListCell *cell;
2475  Node *expr;
2476  CookedConstraint *cooked;
2477 
2478  /*
2479  * Get info about existing constraints.
2480  */
2481  tupleDesc = RelationGetDescr(rel);
2482  oldconstr = tupleDesc->constr;
2483  if (oldconstr)
2484  numoldchecks = oldconstr->num_check;
2485  else
2486  numoldchecks = 0;
2487 
2488  /*
2489  * Create a dummy ParseState and insert the target relation as its sole
2490  * rangetable entry. We need a ParseState for transformExpr.
2491  */
2492  pstate = make_parsestate(NULL);
2493  rte = addRangeTableEntryForRelation(pstate,
2494  rel,
2495  NULL,
2496  false,
2497  true);
2498  addRTEtoQuery(pstate, rte, true, true, true);
2499 
2500  /*
2501  * Process column default expressions.
2502  */
2503  foreach(cell, newColDefaults)
2504  {
2505  RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
2506  Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
2507  Oid defOid;
2508 
2509  expr = cookDefault(pstate, colDef->raw_default,
2510  atp->atttypid, atp->atttypmod,
2511  NameStr(atp->attname));
2512 
2513  /*
2514  * If the expression is just a NULL constant, we do not bother to make
2515  * an explicit pg_attrdef entry, since the default behavior is
2516  * equivalent.
2517  *
2518  * Note a nonobvious property of this test: if the column is of a
2519  * domain type, what we'll get is not a bare null Const but a
2520  * CoerceToDomain expr, so we will not discard the default. This is
2521  * critical because the column default needs to be retained to
2522  * override any default that the domain might have.
2523  */
2524  if (expr == NULL ||
2525  (IsA(expr, Const) &&((Const *) expr)->constisnull))
2526  continue;
2527 
2528  /* If the DEFAULT is volatile we cannot use a missing value */
2529  if (colDef->missingMode && contain_volatile_functions((Node *) expr))
2530  colDef->missingMode = false;
2531 
2532  defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal,
2533  colDef->missingMode);
2534 
2535  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2536  cooked->contype = CONSTR_DEFAULT;
2537  cooked->conoid = defOid;
2538  cooked->name = NULL;
2539  cooked->attnum = colDef->attnum;
2540  cooked->expr = expr;
2541  cooked->skip_validation = false;
2542  cooked->is_local = is_local;
2543  cooked->inhcount = is_local ? 0 : 1;
2544  cooked->is_no_inherit = false;
2545  cookedConstraints = lappend(cookedConstraints, cooked);
2546  }
2547 
2548  /*
2549  * Process constraint expressions.
2550  */
2551  numchecks = numoldchecks;
2552  checknames = NIL;
2553  foreach(cell, newConstraints)
2554  {
2555  Constraint *cdef = (Constraint *) lfirst(cell);
2556  char *ccname;
2557  Oid constrOid;
2558 
2559  if (cdef->contype != CONSTR_CHECK)
2560  continue;
2561 
2562  if (cdef->raw_expr != NULL)
2563  {
2564  Assert(cdef->cooked_expr == NULL);
2565 
2566  /*
2567  * Transform raw parsetree to executable expression, and verify
2568  * it's valid as a CHECK constraint.
2569  */
2570  expr = cookConstraint(pstate, cdef->raw_expr,
2572  }
2573  else
2574  {
2575  Assert(cdef->cooked_expr != NULL);
2576 
2577  /*
2578  * Here, we assume the parser will only pass us valid CHECK
2579  * expressions, so we do no particular checking.
2580  */
2581  expr = stringToNode(cdef->cooked_expr);
2582  }
2583 
2584  /*
2585  * Check name uniqueness, or generate a name if none was given.
2586  */
2587  if (cdef->conname != NULL)
2588  {
2589  ListCell *cell2;
2590 
2591  ccname = cdef->conname;
2592  /* Check against other new constraints */
2593  /* Needed because we don't do CommandCounterIncrement in loop */
2594  foreach(cell2, checknames)
2595  {
2596  if (strcmp((char *) lfirst(cell2), ccname) == 0)
2597  ereport(ERROR,
2599  errmsg("check constraint \"%s\" already exists",
2600  ccname)));
2601  }
2602 
2603  /* save name for future checks */
2604  checknames = lappend(checknames, ccname);
2605 
2606  /*
2607  * Check against pre-existing constraints. If we are allowed to
2608  * merge with an existing constraint, there's no more to do here.
2609  * (We omit the duplicate constraint from the result, which is
2610  * what ATAddCheckConstraint wants.)
2611  */
2612  if (MergeWithExistingConstraint(rel, ccname, expr,
2613  allow_merge, is_local,
2614  cdef->initially_valid,
2615  cdef->is_no_inherit))
2616  continue;
2617  }
2618  else
2619  {
2620  /*
2621  * When generating a name, we want to create "tab_col_check" for a
2622  * column constraint and "tab_check" for a table constraint. We
2623  * no longer have any info about the syntactic positioning of the
2624  * constraint phrase, so we approximate this by seeing whether the
2625  * expression references more than one column. (If the user
2626  * played by the rules, the result is the same...)
2627  *
2628  * Note: pull_var_clause() doesn't descend into sublinks, but we
2629  * eliminated those above; and anyway this only needs to be an
2630  * approximate answer.
2631  */
2632  List *vars;
2633  char *colname;
2634 
2635  vars = pull_var_clause(expr, 0);
2636 
2637  /* eliminate duplicates */
2638  vars = list_union(NIL, vars);
2639 
2640  if (list_length(vars) == 1)
2641  colname = get_attname(RelationGetRelid(rel),
2642  ((Var *) linitial(vars))->varattno,
2643  true);
2644  else
2645  colname = NULL;
2646 
2648  colname,
2649  "check",
2650  RelationGetNamespace(rel),
2651  checknames);
2652 
2653  /* save name for future checks */
2654  checknames = lappend(checknames, ccname);
2655  }
2656 
2657  /*
2658  * OK, store it.
2659  */
2660  constrOid =
2661  StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
2662  is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
2663 
2664  numchecks++;
2665 
2666  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2667  cooked->contype = CONSTR_CHECK;
2668  cooked->conoid = constrOid;
2669  cooked->name = ccname;
2670  cooked->attnum = 0;
2671  cooked->expr = expr;
2672  cooked->skip_validation = cdef->skip_validation;
2673  cooked->is_local = is_local;
2674  cooked->inhcount = is_local ? 0 : 1;
2675  cooked->is_no_inherit = cdef->is_no_inherit;
2676  cookedConstraints = lappend(cookedConstraints, cooked);
2677  }
2678 
2679  /*
2680  * Update the count of constraints in the relation's pg_class tuple. We do
2681  * this even if there was no change, in order to ensure that an SI update
2682  * message is sent out for the pg_class tuple, which will force other
2683  * backends to rebuild their relcache entries for the rel. (This is
2684  * critical if we added defaults but not constraints.)
2685  */
2686  SetRelationNumChecks(rel, numchecks);
2687 
2688  return cookedConstraints;
2689 }
#define NIL
Definition: pg_list.h:69
char * ChooseConstraintName(const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
void * stringToNode(char *str)
Definition: read.c:39
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2852
bool is_no_inherit
Definition: heap.h:39
AttrNumber attnum
Definition: heap.h:24
#define RelationGetDescr(relation)
Definition: rel.h:433
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
Node * raw_expr
Definition: parsenodes.h:2102
static Node * cookConstraint(ParseState *pstate, Node *raw_constraint, char *relname)
Definition: heap.c:2966
Definition: nodes.h:516
int errcode(int sqlerrcode)
Definition: elog.c:575
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
List * list_union(const List *list1, const List *list2)
Definition: list.c:697
char * conname
Definition: parsenodes.h:2095
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:958
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:163
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname)
Definition: heap.c:2895
AttrNumber attnum
Definition: heap.h:34
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
bool missingMode
Definition: heap.h:26
int inhcount
Definition: heap.h:38
#define RelationGetRelationName(relation)
Definition: rel.h:441
Node * raw_default
Definition: heap.h:25
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
bool skip_validation
Definition: heap.h:36
ConstrType contype
Definition: heap.h:31
#define ereport(elevel, rest)
Definition: elog.h:122
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
List * lappend(List *list, void *datum)
Definition: list.c:128
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal, bool add_column_mode)
Definition: heap.c:2096
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:2702
TupleDesc rd_att
Definition: rel.h:85
bool is_no_inherit
Definition: parsenodes.h:2101
bool initially_valid
Definition: parsenodes.h:2136
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
TupleConstr * constr
Definition: tupdesc.h:87
static int list_length(const List *l)
Definition: pg_list.h:89
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, Alias *alias, bool inh, bool inFromCl)
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid conoid
Definition: heap.h:32
#define NameStr(name)
Definition: c.h:576
ConstrType contype
Definition: parsenodes.h:2092
Node * expr
Definition: heap.h:35
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
uint16 num_check
Definition: tupdesc.h:45
char * cooked_expr
Definition: parsenodes.h:2103
Definition: regcomp.c:224
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
Definition: pg_list.h:45
bool skip_validation
Definition: parsenodes.h:2135
char * name
Definition: heap.h:33
#define RelationGetRelid(relation)
Definition: rel.h:407
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:2270
bool is_local
Definition: heap.h:37
#define RelationGetNamespace(relation)
Definition: rel.h:448

◆ CheckAttributeNamesTypes()

void CheckAttributeNamesTypes ( TupleDesc  tupdesc,
char  relkind,
bool  allow_system_table_mods 
)

Definition at line 414 of file heap.c.

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

Referenced by addRangeTableEntryForFunction(), and heap_create_with_catalog().

416 {
417  int i;
418  int j;
419  int natts = tupdesc->natts;
420 
421  /* Sanity check on column count */
422  if (natts < 0 || natts > MaxHeapAttributeNumber)
423  ereport(ERROR,
424  (errcode(ERRCODE_TOO_MANY_COLUMNS),
425  errmsg("tables can have at most %d columns",
426  MaxHeapAttributeNumber)));
427 
428  /*
429  * first check for collision with system attribute names
430  *
431  * Skip this for a view or type relation, since those don't have system
432  * attributes.
433  */
434  if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
435  {
436  for (i = 0; i < natts; i++)
437  {
438  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
439 
440  if (SystemAttributeByName(NameStr(attr->attname),
441  tupdesc->tdhasoid) != NULL)
442  ereport(ERROR,
443  (errcode(ERRCODE_DUPLICATE_COLUMN),
444  errmsg("column name \"%s\" conflicts with a system column name",
445  NameStr(attr->attname))));
446  }
447  }
448 
449  /*
450  * next check for repeated attribute names
451  */
452  for (i = 1; i < natts; i++)
453  {
454  for (j = 0; j < i; j++)
455  {
456  if (strcmp(NameStr(TupleDescAttr(tupdesc, j)->attname),
457  NameStr(TupleDescAttr(tupdesc, i)->attname)) == 0)
458  ereport(ERROR,
459  (errcode(ERRCODE_DUPLICATE_COLUMN),
460  errmsg("column name \"%s\" specified more than once",
461  NameStr(TupleDescAttr(tupdesc, j)->attname))));
462  }
463  }
464 
465  /*
466  * next check the attribute types
467  */
468  for (i = 0; i < natts; i++)
469  {
471  TupleDescAttr(tupdesc, i)->atttypid,
472  TupleDescAttr(tupdesc, i)->attcollation,
473  NIL, /* assume we're creating a new rowtype */
474  allow_system_table_mods);
475  }
476 }
#define NIL
Definition: pg_list.h:69
bool tdhasoid
Definition: tupdesc.h:85
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
Form_pg_attribute SystemAttributeByName(const char *attname, bool relhasoids)
Definition: heap.c:217
int errcode(int sqlerrcode)
Definition: elog.c:575
int natts
Definition: tupdesc.h:82
char relkind
Definition: pg_class.h:51
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
Oid attcollation
Definition: pg_attribute.h:161
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
Oid atttypid
Definition: pg_attribute.h:49
#define ereport(elevel, rest)
Definition: elog.h:122
void CheckAttributeType(const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, bool allow_system_table_mods)
Definition: heap.c:494
#define MaxHeapAttributeNumber
Definition: htup_details.h:47
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:576

◆ CheckAttributeType()

void CheckAttributeType ( const char *  attname,
Oid  atttypid,
Oid  attcollation,
List containing_rowtypes,
bool  allow_system_table_mods 
)

Definition at line 494 of file heap.c.

References AccessShareLock, CheckAttributeType(), ereport, errcode(), errhint(), errmsg(), ERROR, format_type_be(), get_element_type(), get_typ_typrelid(), get_typtype(), getBaseType(), i, lcons_oid(), list_delete_first(), list_member_oid(), NameStr, tupleDesc::natts, OidIsValid, relation_close(), relation_open(), RelationGetDescr, TupleDescAttr, and type_is_collatable().

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

498 {
499  char att_typtype = get_typtype(atttypid);
500  Oid att_typelem;
501 
502  if (att_typtype == TYPTYPE_PSEUDO)
503  {
504  /*
505  * Refuse any attempt to create a pseudo-type column, except for a
506  * special hack for pg_statistic: allow ANYARRAY when modifying system
507  * catalogs (this allows creating pg_statistic and cloning it during
508  * VACUUM FULL)
509  */
510  if (atttypid != ANYARRAYOID || !allow_system_table_mods)
511  ereport(ERROR,
512  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
513  errmsg("column \"%s\" has pseudo-type %s",
515  }
516  else if (att_typtype == TYPTYPE_DOMAIN)
517  {
518  /*
519  * If it's a domain, recurse to check its base type.
520  */
522  containing_rowtypes,
523  allow_system_table_mods);
524  }
525  else if (att_typtype == TYPTYPE_COMPOSITE)
526  {
527  /*
528  * For a composite type, recurse into its attributes.
529  */
530  Relation relation;
531  TupleDesc tupdesc;
532  int i;
533 
534  /*
535  * Check for self-containment. Eventually we might be able to allow
536  * this (just return without complaint, if so) but it's not clear how
537  * many other places would require anti-recursion defenses before it
538  * would be safe to allow tables to contain their own rowtype.
539  */
540  if (list_member_oid(containing_rowtypes, atttypid))
541  ereport(ERROR,
542  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
543  errmsg("composite type %s cannot be made a member of itself",
545 
546  containing_rowtypes = lcons_oid(atttypid, containing_rowtypes);
547 
549 
550  tupdesc = RelationGetDescr(relation);
551 
552  for (i = 0; i < tupdesc->natts; i++)
553  {
554  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
555 
556  if (attr->attisdropped)
557  continue;
558  CheckAttributeType(NameStr(attr->attname),
559  attr->atttypid, attr->attcollation,
560  containing_rowtypes,
561  allow_system_table_mods);
562  }
563 
564  relation_close(relation, AccessShareLock);
565 
566  containing_rowtypes = list_delete_first(containing_rowtypes);
567  }
568  else if (OidIsValid((att_typelem = get_element_type(atttypid))))
569  {
570  /*
571  * Must recurse into array types, too, in case they are composite.
572  */
574  containing_rowtypes,
575  allow_system_table_mods);
576  }
577 
578  /*
579  * This might not be strictly invalid per SQL standard, but it is pretty
580  * useless, and it cannot be dumped, so we must disallow it.
581  */
583  ereport(ERROR,
584  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
585  errmsg("no collation was derived for column \"%s\" with collatable type %s",
587  errhint("Use the COLLATE clause to set the collation explicitly.")));
588 }
int errhint(const char *fmt,...)
Definition: elog.c:987
#define RelationGetDescr(relation)
Definition: rel.h:433
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2502
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
char get_typtype(Oid typid)
Definition: lsyscache.c:2383
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1270
char * format_type_be(Oid type_oid)
Definition: format_type.c:328
List * lcons_oid(Oid datum, List *list)
Definition: list.c:295
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
int natts
Definition: tupdesc.h:82
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2475
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
Oid attcollation
Definition: pg_attribute.h:161
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
Oid atttypid
Definition: pg_attribute.h:49
#define ereport(elevel, rest)
Definition: elog.h:122
void CheckAttributeType(const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, bool allow_system_table_mods)
Definition: heap.c:494
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define NameStr(name)
Definition: c.h:576
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1124
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2275
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:2824
List * list_delete_first(List *list)
Definition: list.c:666

◆ cookDefault()

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

Definition at line 2895 of file heap.c.

References Assert, assign_expr_collations(), COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, contain_var_clause(), ereport, errcode(), errhint(), errmsg(), ERROR, EXPR_KIND_COLUMN_DEFAULT, exprType(), format_type_be(), OidIsValid, and transformExpr().

Referenced by AddRelationNewConstraints(), AlterDomainDefault(), and DefineDomain().

2900 {
2901  Node *expr;
2902 
2903  Assert(raw_default != NULL);
2904 
2905  /*
2906  * Transform raw parsetree to executable expression.
2907  */
2908  expr = transformExpr(pstate, raw_default, EXPR_KIND_COLUMN_DEFAULT);
2909 
2910  /*
2911  * Make sure default expr does not refer to any vars (we need this check
2912  * since the pstate includes the target table).
2913  */
2914  if (contain_var_clause(expr))
2915  ereport(ERROR,
2916  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2917  errmsg("cannot use column references in default expression")));
2918 
2919  /*
2920  * transformExpr() should have already rejected subqueries, aggregates,
2921  * window functions, and SRFs, based on the EXPR_KIND_ for a default
2922  * expression.
2923  */
2924 
2925  /*
2926  * Coerce the expression to the correct type and typmod, if given. This
2927  * should match the parser's processing of non-defaulted expressions ---
2928  * see transformAssignedExpr().
2929  */
2930  if (OidIsValid(atttypid))
2931  {
2932  Oid type_id = exprType(expr);
2933 
2934  expr = coerce_to_target_type(pstate, expr, type_id,
2935  atttypid, atttypmod,
2938  -1);
2939  if (expr == NULL)
2940  ereport(ERROR,
2941  (errcode(ERRCODE_DATATYPE_MISMATCH),
2942  errmsg("column \"%s\" is of type %s"
2943  " but default expression is of type %s",
2944  attname,
2946  format_type_be(type_id)),
2947  errhint("You will need to rewrite or cast the expression.")));
2948  }
2949 
2950  /*
2951  * Finally, take care of collations in the finished expression.
2952  */
2953  assign_expr_collations(pstate, expr);
2954 
2955  return expr;
2956 }
int errhint(const char *fmt,...)
Definition: elog.c:987
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:146
Definition: nodes.h:516
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:328
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
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:122
#define Assert(condition)
Definition: c.h:699
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ DeleteAttributeTuples()

void DeleteAttributeTuples ( Oid  relid)

Definition at line 1474 of file heap.c.

References AttributeRelidNumIndexId, BTEqualStrategyNumber, CatalogTupleDelete(), heap_close, heap_open(), ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by heap_drop_with_catalog(), and index_drop().

1475 {
1476  Relation attrel;
1477  SysScanDesc scan;
1478  ScanKeyData key[1];
1479  HeapTuple atttup;
1480 
1481  /* Grab an appropriate lock on the pg_attribute relation */
1482  attrel = heap_open(AttributeRelationId, RowExclusiveLock);
1483 
1484  /* Use the index to scan only attributes of the target relation */
1485  ScanKeyInit(&key[0],
1486  Anum_pg_attribute_attrelid,
1487  BTEqualStrategyNumber, F_OIDEQ,
1488  ObjectIdGetDatum(relid));
1489 
1490  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1491  NULL, 1, key);
1492 
1493  /* Delete all the matching tuples */
1494  while ((atttup = systable_getnext(scan)) != NULL)
1495  CatalogTupleDelete(attrel, &atttup->t_self);
1496 
1497  /* Clean up after the scan */
1498  systable_endscan(scan);
1499  heap_close(attrel, RowExclusiveLock);
1500 }
#define AttributeRelidNumIndexId
Definition: indexing.h:93
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ DeleteRelationTuple()

void DeleteRelationTuple ( Oid  relid)

Definition at line 1445 of file heap.c.

References CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), RELOID, RowExclusiveLock, SearchSysCache1(), and HeapTupleData::t_self.

Referenced by heap_drop_with_catalog(), and index_drop().

1446 {
1447  Relation pg_class_desc;
1448  HeapTuple tup;
1449 
1450  /* Grab an appropriate lock on the pg_class relation */
1451  pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);
1452 
1453  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1454  if (!HeapTupleIsValid(tup))
1455  elog(ERROR, "cache lookup failed for relation %u", relid);
1456 
1457  /* delete the relation tuple from pg_class, and finish up */
1458  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1459 
1460  ReleaseSysCache(tup);
1461 
1462  heap_close(pg_class_desc, RowExclusiveLock);
1463 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#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:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog
Definition: elog.h:219

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

Definition at line 1511 of file heap.c.

References AttributeRelidNumIndexId, BTEqualStrategyNumber, BTLessEqualStrategyNumber, CatalogTupleDelete(), heap_close, heap_open(), Int16GetDatum, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by DefineQueryRewrite().

1512 {
1513  Relation attrel;
1514  SysScanDesc scan;
1515  ScanKeyData key[2];
1516  HeapTuple atttup;
1517 
1518  /* Grab an appropriate lock on the pg_attribute relation */
1519  attrel = heap_open(AttributeRelationId, RowExclusiveLock);
1520 
1521  /* Use the index to scan only system attributes of the target relation */
1522  ScanKeyInit(&key[0],
1523  Anum_pg_attribute_attrelid,
1524  BTEqualStrategyNumber, F_OIDEQ,
1525  ObjectIdGetDatum(relid));
1526  ScanKeyInit(&key[1],
1527  Anum_pg_attribute_attnum,
1528  BTLessEqualStrategyNumber, F_INT2LE,
1529  Int16GetDatum(0));
1530 
1531  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1532  NULL, 2, key);
1533 
1534  /* Delete all the matching tuples */
1535  while ((atttup = systable_getnext(scan)) != NULL)
1536  CatalogTupleDelete(attrel, &atttup->t_self);
1537 
1538  /* Clean up after the scan */
1539  systable_endscan(scan);
1540  heap_close(attrel, RowExclusiveLock);
1541 }
#define AttributeRelidNumIndexId
Definition: indexing.h:93
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define Int16GetDatum(X)
Definition: postgres.h:436
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ heap_create()

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

Definition at line 253 of file heap.c.

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

Referenced by heap_create_with_catalog(), and index_create().

264 {
265  bool create_storage;
266  Relation rel;
267 
268  /* The caller must have provided an OID for the relation. */
269  Assert(OidIsValid(relid));
270 
271  /*
272  * Don't allow creating relations in pg_catalog directly, even though it
273  * is allowed to move user defined relations there. Semantics with search
274  * paths including pg_catalog are too confusing for now.
275  *
276  * But allow creating indexes on relations in pg_catalog even if
277  * allow_system_table_mods = off, upper layers already guarantee it's on a
278  * user defined relation, not a system one.
279  */
280  if (!allow_system_table_mods &&
281  ((IsSystemNamespace(relnamespace) && relkind != RELKIND_INDEX) ||
284  ereport(ERROR,
285  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
286  errmsg("permission denied to create \"%s.%s\"",
287  get_namespace_name(relnamespace), relname),
288  errdetail("System catalog modifications are currently disallowed.")));
289 
290  /*
291  * Decide if we need storage or not, and handle a couple other special
292  * cases for particular relkinds.
293  */
294  switch (relkind)
295  {
296  case RELKIND_VIEW:
297  case RELKIND_COMPOSITE_TYPE:
298  case RELKIND_FOREIGN_TABLE:
299  case RELKIND_PARTITIONED_TABLE:
300  case RELKIND_PARTITIONED_INDEX:
301  create_storage = false;
302 
303  /*
304  * Force reltablespace to zero if the relation has no physical
305  * storage. This is mainly just for cleanliness' sake.
306  */
308  break;
309  case RELKIND_SEQUENCE:
310  create_storage = true;
311 
312  /*
313  * Force reltablespace to zero for sequences, since we don't
314  * support moving them around into different tablespaces.
315  */
317  break;
318  default:
319  create_storage = true;
320  break;
321  }
322 
323  /*
324  * Unless otherwise requested, the physical ID (relfilenode) is initially
325  * the same as the logical ID (OID). When the caller did specify a
326  * relfilenode, it already exists; do not attempt to create it.
327  */
328  if (OidIsValid(relfilenode))
329  create_storage = false;
330  else
331  relfilenode = relid;
332 
333  /*
334  * Never allow a pg_class entry to explicitly specify the database's
335  * default tablespace in reltablespace; force it to zero instead. This
336  * ensures that if the database is cloned with a different default
337  * tablespace, the pg_class entry will still match where CREATE DATABASE
338  * will put the physically copied relation.
339  *
340  * Yes, this is a bit of a hack.
341  */
344 
345  /*
346  * build the relcache entry.
347  */
348  rel = RelationBuildLocalRelation(relname,
349  relnamespace,
350  tupDesc,
351  relid,
352  relfilenode,
354  shared_relation,
355  mapped_relation,
357  relkind);
358 
359  /*
360  * Have the storage manager create the relation's disk file, if needed.
361  *
362  * We only create the main fork here, other forks will be created on
363  * demand.
364  */
365  if (create_storage)
366  {
367  RelationOpenSmgr(rel);
369  }
370 
371  return rel;
372 }
Relation RelationBuildLocalRelation(const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid relfilenode, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
Definition: relcache.c:3094
Oid relnamespace
Definition: pg_class.h:32
int errcode(int sqlerrcode)
Definition: elog.c:575
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:177
#define OidIsValid(objectId)
Definition: c.h:605
char relkind
Definition: pg_class.h:51
Oid MyDatabaseTableSpace
Definition: globals.c:86
#define RelationOpenSmgr(relation)
Definition: rel.h:465
#define ERROR
Definition: elog.h:43
char relpersistence
Definition: pg_class.h:50
Oid relfilenode
Definition: pg_class.h:39
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
#define IsNormalProcessingMode()
Definition: miscadmin.h:374
Oid reltablespace
Definition: pg_class.h:42
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:163
#define InvalidOid
Definition: postgres_ext.h:36
RelFileNode rd_node
Definition: rel.h:55
#define Assert(condition)
Definition: c.h:699
int errmsg(const char *fmt,...)
Definition: elog.c:797
void RelationCreateStorage(RelFileNode rnode, char relpersistence)
Definition: storage.c:77

◆ heap_create_init_fork()

void heap_create_init_fork ( Relation  rel)

Definition at line 1391 of file heap.c.

References Assert, INIT_FORKNUM, log_smgrcreate(), RelFileNodeBackend::node, RelationData::rd_rel, RelationData::rd_smgr, RelationOpenSmgr, SMgrRelationData::smgr_rnode, smgrcreate(), and smgrimmedsync().

Referenced by ExecuteTruncateGuts(), and heap_create_with_catalog().

1392 {
1393  Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
1394  rel->rd_rel->relkind == RELKIND_MATVIEW ||
1395  rel->rd_rel->relkind == RELKIND_TOASTVALUE);
1396  RelationOpenSmgr(rel);
1397  smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
1400 }
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:376
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
Form_pg_class rd_rel
Definition: rel.h:84
#define RelationOpenSmgr(relation)
Definition: rel.h:465
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:699
void log_smgrcreate(RelFileNode *rnode, ForkNumber forkNum)
Definition: storage.c:124
void smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:734

◆ heap_create_with_catalog()

Oid heap_create_with_catalog ( const char *  relname,
Oid  relnamespace,
Oid  reltablespace,
Oid  relid,
Oid  reltypeid,
Oid  reloftypeid,
Oid  ownerid,
TupleDesc  tupdesc,
List cooked_constraints,
char  relkind,
char  relpersistence,
bool  shared_relation,
bool  mapped_relation,
bool  oidislocal,
int  oidinhcount,
OnCommitAction  oncommit,
Datum  reloptions,
bool  use_user_acl,
bool  allow_system_table_mods,
bool  is_internal,
Oid  relrewrite,
ObjectAddress typaddress 
)

Definition at line 1027 of file heap.c.

References aclmembers(), AddNewAttributeTuples(), AddNewRelationTuple(), AddNewRelationType(), Assert, AssignTypeArrayOid(), binary_upgrade_next_heap_pg_class_oid, binary_upgrade_next_toast_pg_class_oid, CheckAttributeNamesTypes(), 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_close, heap_create(), heap_create_init_fork(), heap_open(), 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(), recordDependencyOnOwner(), register_on_commit_action(), RelationGetRelid, relnamespace, relrewrite, RowExclusiveLock, StoreConstraints(), TypeCreate(), TYPENAMENSP, and updateAclDependencies().

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

1049 {
1050  Relation pg_class_desc;
1051  Relation new_rel_desc;
1052  Acl *relacl;
1053  Oid existing_relid;
1054  Oid old_type_oid;
1055  Oid new_type_oid;
1056  ObjectAddress new_type_addr;
1057  Oid new_array_oid = InvalidOid;
1058 
1059  pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);
1060 
1061  /*
1062  * sanity checks
1063  */
1065 
1066  CheckAttributeNamesTypes(tupdesc, relkind, allow_system_table_mods);
1067 
1068  /*
1069  * This would fail later on anyway, if the relation already exists. But
1070  * by catching it here we can emit a nicer error message.
1071  */
1072  existing_relid = get_relname_relid(relname, relnamespace);
1073  if (existing_relid != InvalidOid)
1074  ereport(ERROR,
1075  (errcode(ERRCODE_DUPLICATE_TABLE),
1076  errmsg("relation \"%s\" already exists", relname)));
1077 
1078  /*
1079  * Since we are going to create a rowtype as well, also check for
1080  * collision with an existing type name. If there is one and it's an
1081  * autogenerated array, we can rename it out of the way; otherwise we can
1082  * at least give a good error message.
1083  */
1084  old_type_oid = GetSysCacheOid2(TYPENAMENSP,
1085  CStringGetDatum(relname),
1087  if (OidIsValid(old_type_oid))
1088  {
1089  if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
1090  ereport(ERROR,
1092  errmsg("type \"%s\" already exists", relname),
1093  errhint("A relation has an associated type of the same name, "
1094  "so you must use a name that doesn't conflict "
1095  "with any existing type.")));
1096  }
1097 
1098  /*
1099  * Shared relations must be in pg_global (last-ditch check)
1100  */
1101  if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
1102  elog(ERROR, "shared relations must be placed in pg_global tablespace");
1103 
1104  /*
1105  * Allocate an OID for the relation, unless we were told what to use.
1106  *
1107  * The OID will be the relfilenode as well, so make sure it doesn't
1108  * collide with either pg_class OIDs or existing physical files.
1109  */
1110  if (!OidIsValid(relid))
1111  {
1112  /* Use binary-upgrade override for pg_class.oid/relfilenode? */
1113  if (IsBinaryUpgrade &&
1114  (relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
1115  relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
1116  relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE ||
1117  relkind == RELKIND_PARTITIONED_TABLE))
1118  {
1120  ereport(ERROR,
1121  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1122  errmsg("pg_class heap OID value not set when in binary upgrade mode")));
1123 
1126  }
1127  /* There might be no TOAST table, so we have to test for it. */
1128  else if (IsBinaryUpgrade &&
1130  relkind == RELKIND_TOASTVALUE)
1131  {
1134  }
1135  else
1136  relid = GetNewRelFileNode(reltablespace, pg_class_desc,
1137  relpersistence);
1138  }
1139 
1140  /*
1141  * Determine the relation's initial permissions.
1142  */
1143  if (use_user_acl)
1144  {
1145  switch (relkind)
1146  {
1147  case RELKIND_RELATION:
1148  case RELKIND_VIEW:
1149  case RELKIND_MATVIEW:
1150  case RELKIND_FOREIGN_TABLE:
1151  case RELKIND_PARTITIONED_TABLE:
1152  relacl = get_user_default_acl(OBJECT_TABLE, ownerid,
1153  relnamespace);
1154  break;
1155  case RELKIND_SEQUENCE:
1156  relacl = get_user_default_acl(OBJECT_SEQUENCE, ownerid,
1157  relnamespace);
1158  break;
1159  default:
1160  relacl = NULL;
1161  break;
1162  }
1163  }
1164  else
1165  relacl = NULL;
1166 
1167  /*
1168  * Create the relcache entry (mostly dummy at this point) and the physical
1169  * disk file. (If we fail further down, it's the smgr's responsibility to
1170  * remove the disk file again.)
1171  */
1172  new_rel_desc = heap_create(relname,
1173  relnamespace,
1174  reltablespace,
1175  relid,
1176  InvalidOid,
1177  tupdesc,
1178  relkind,
1180  shared_relation,
1181  mapped_relation,
1182  allow_system_table_mods);
1183 
1184  Assert(relid == RelationGetRelid(new_rel_desc));
1185 
1186  new_rel_desc->rd_rel->relrewrite = relrewrite;
1187 
1188  /*
1189  * Decide whether to create an array type over the relation's rowtype. We
1190  * do not create any array types for system catalogs (ie, those made
1191  * during initdb). We do not create them where the use of a relation as
1192  * such is an implementation detail: toast tables, sequences and indexes.
1193  */
1194  if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
1195  relkind == RELKIND_VIEW ||
1196  relkind == RELKIND_MATVIEW ||
1197  relkind == RELKIND_FOREIGN_TABLE ||
1198  relkind == RELKIND_COMPOSITE_TYPE ||
1199  relkind == RELKIND_PARTITIONED_TABLE))
1200  new_array_oid = AssignTypeArrayOid();
1201 
1202  /*
1203  * Since defining a relation also defines a complex type, we add a new
1204  * system type corresponding to the new relation. The OID of the type can
1205  * be preselected by the caller, but if reltypeid is InvalidOid, we'll
1206  * generate a new OID for it.
1207  *
1208  * NOTE: we could get a unique-index failure here, in case someone else is
1209  * creating the same type name in parallel but hadn't committed yet when
1210  * we checked for a duplicate name above.
1211  */
1212  new_type_addr = AddNewRelationType(relname,
1213  relnamespace,
1214  relid,
1215  relkind,
1216  ownerid,
1217  reltypeid,
1218  new_array_oid);
1219  new_type_oid = new_type_addr.objectId;
1220  if (typaddress)
1221  *typaddress = new_type_addr;
1222 
1223  /*
1224  * Now make the array type if wanted.
1225  */
1226  if (OidIsValid(new_array_oid))
1227  {
1228  char *relarrayname;
1229 
1230  relarrayname = makeArrayTypeName(relname, relnamespace);
1231 
1232  TypeCreate(new_array_oid, /* force the type's OID to this */
1233  relarrayname, /* Array type name */
1234  relnamespace, /* Same namespace as parent */
1235  InvalidOid, /* Not composite, no relationOid */
1236  0, /* relkind, also N/A here */
1237  ownerid, /* owner's ID */
1238  -1, /* Internal size (varlena) */
1239  TYPTYPE_BASE, /* Not composite - typelem is */
1240  TYPCATEGORY_ARRAY, /* type-category (array) */
1241  false, /* array types are never preferred */
1242  DEFAULT_TYPDELIM, /* default array delimiter */
1243  F_ARRAY_IN, /* array input proc */
1244  F_ARRAY_OUT, /* array output proc */
1245  F_ARRAY_RECV, /* array recv (bin) proc */
1246  F_ARRAY_SEND, /* array send (bin) proc */
1247  InvalidOid, /* typmodin procedure - none */
1248  InvalidOid, /* typmodout procedure - none */
1249  F_ARRAY_TYPANALYZE, /* array analyze procedure */
1250  new_type_oid, /* array element type - the rowtype */
1251  true, /* yes, this is an array type */
1252  InvalidOid, /* this has no array type */
1253  InvalidOid, /* domain base type - irrelevant */
1254  NULL, /* default value - none */
1255  NULL, /* default binary representation */
1256  false, /* passed by reference */
1257  'd', /* alignment - must be the largest! */
1258  'x', /* fully TOASTable */
1259  -1, /* typmod */
1260  0, /* array dimensions for typBaseType */
1261  false, /* Type NOT NULL */
1262  InvalidOid); /* rowtypes never have a collation */
1263 
1264  pfree(relarrayname);
1265  }
1266 
1267  /*
1268  * now create an entry in pg_class for the relation.
1269  *
1270  * NOTE: we could get a unique-index failure here, in case someone else is
1271  * creating the same relation name in parallel but hadn't committed yet
1272  * when we checked for a duplicate name above.
1273  */
1274  AddNewRelationTuple(pg_class_desc,
1275  new_rel_desc,
1276  relid,
1277  new_type_oid,
1278  reloftypeid,
1279  ownerid,
1280  relkind,
1281  PointerGetDatum(relacl),
1282  reloptions);
1283 
1284  /*
1285  * now add tuples to pg_attribute for the attributes in our new relation.
1286  */
1287  AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind,
1288  oidislocal, oidinhcount);
1289 
1290  /*
1291  * Make a dependency link to force the relation to be deleted if its
1292  * namespace is. Also make a dependency link to its owner, as well as
1293  * dependencies for any roles mentioned in the default ACL.
1294  *
1295  * For composite types, these dependencies are tracked for the pg_type
1296  * entry, so we needn't record them here. Likewise, TOAST tables don't
1297  * need a namespace dependency (they live in a pinned namespace) nor an
1298  * owner dependency (they depend indirectly through the parent table), nor
1299  * should they have any ACL entries. The same applies for extension
1300  * dependencies.
1301  *
1302  * Also, skip this in bootstrap mode, since we don't make dependencies
1303  * while bootstrapping.
1304  */
1305  if (relkind != RELKIND_COMPOSITE_TYPE &&
1306  relkind != RELKIND_TOASTVALUE &&
1308  {
1309  ObjectAddress myself,
1310  referenced;
1311 
1312  myself.classId = RelationRelationId;
1313  myself.objectId = relid;
1314  myself.objectSubId = 0;
1315  referenced.classId = NamespaceRelationId;
1316  referenced.objectId = relnamespace;
1317  referenced.objectSubId = 0;
1318  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1319 
1320  recordDependencyOnOwner(RelationRelationId, relid, ownerid);
1321 
1322  recordDependencyOnCurrentExtension(&myself, false);
1323 
1324  if (reloftypeid)
1325  {
1326  referenced.classId = TypeRelationId;
1327  referenced.objectId = reloftypeid;
1328  referenced.objectSubId = 0;
1329  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1330  }
1331 
1332  if (relacl != NULL)
1333  {
1334  int nnewmembers;
1335  Oid *newmembers;
1336 
1337  nnewmembers = aclmembers(relacl, &newmembers);
1338  updateAclDependencies(RelationRelationId, relid, 0,
1339  ownerid,
1340  0, NULL,
1341  nnewmembers, newmembers);
1342  }
1343  }
1344 
1345  /* Post creation hook for new relation */
1346  InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
1347 
1348  /*
1349  * Store any supplied constraints and defaults.
1350  *
1351  * NB: this may do a CommandCounterIncrement and rebuild the relcache
1352  * entry, so the relation must be valid and self-consistent at this point.
1353  * In particular, there are not yet constraints and defaults anywhere.
1354  */
1355  StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
1356 
1357  /*
1358  * If there's a special on-commit action, remember it
1359  */
1360  if (oncommit != ONCOMMIT_NOOP)
1361  register_on_commit_action(relid, oncommit);
1362 
1363  /*
1364  * Unlogged objects need an init fork, except for partitioned tables which
1365  * have no storage at all.
1366  */
1367  if (relpersistence == RELPERSISTENCE_UNLOGGED &&
1368  relkind != RELKIND_PARTITIONED_TABLE)
1369  heap_create_init_fork(new_rel_desc);
1370 
1371  /*
1372  * ok, the relation has been cataloged, so close our relations and return
1373  * the OID of the newly created relation.
1374  */
1375  heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
1376  heap_close(pg_class_desc, RowExclusiveLock);
1377 
1378  return relid;
1379 }
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
void register_on_commit_action(Oid relid, OnCommitAction action)
Definition: tablecmds.c:13175
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:766
int errhint(const char *fmt,...)
Definition: elog.c:987
Oid relnamespace
Definition: pg_class.h:32
void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, bool allow_system_table_mods)
Definition: heap.c:414
Oid binary_upgrade_next_heap_pg_class_oid
Definition: heap.c:89
Oid binary_upgrade_next_toast_pg_class_oid
Definition: heap.c:90
#define PointerGetDatum(X)
Definition: postgres.h:541
int errcode(int sqlerrcode)
Definition: elog.c:575
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
#define heap_close(r, l)
Definition: heapam.h:97
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:159
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
bool IsBinaryUpgrade
Definition: globals.c:109
char relkind
Definition: pg_class.h:51
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
Relation heap_create(const char *relname, Oid relnamespace, Oid reltablespace, Oid relid, Oid relfilenode, TupleDesc tupDesc, char relkind, char relpersistence, bool shared_relation, bool mapped_relation, bool allow_system_table_mods)
Definition: heap.c:253
char relpersistence
Definition: pg_class.h:50
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:832
#define IsNormalProcessingMode()
Definition: miscadmin.h:374
void heap_create_init_fork(Relation rel)
Definition: heap.c:1391
Oid reltablespace
Definition: pg_class.h:42
bool IsUnderPostmaster
Definition: globals.c:108
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:563
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:950
static void StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
Definition: heap.c:2389
Oid relrewrite
Definition: pg_class.h:70
#define ereport(elevel, rest)
Definition: elog.h:122
static void AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc, char relkind, bool oidislocal, int oidinhcount)
Definition: heap.c:662
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:147
TupleDesc rd_att
Definition: rel.h:85
#define InvalidOid
Definition: postgres_ext.h:36
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define Assert(condition)
Definition: c.h:699
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:396
Oid AssignTypeArrayOid(void)
Definition: typecmds.c:2095
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, Datum relacl, Datum reloptions)
Definition: heap.c:851
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:372
int errmsg(const char *fmt,...)
Definition: elog.c:797
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:194
#define elog
Definition: elog.h:219
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
#define RelationGetRelid(relation)
Definition: rel.h:407
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:5451

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

Definition at line 1790 of file heap.c.

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

Referenced by doDeletion().

1791 {
1792  Relation rel;
1793  HeapTuple tuple;
1794  Oid parentOid = InvalidOid,
1795  defaultPartOid = InvalidOid;
1796 
1797  /*
1798  * To drop a partition safely, we must grab exclusive lock on its parent,
1799  * because another backend might be about to execute a query on the parent
1800  * table. If it relies on previously cached partition descriptor, then it
1801  * could attempt to access the just-dropped relation as its partition. We
1802  * must therefore take a table lock strong enough to prevent all queries
1803  * on the table from proceeding until we commit and send out a
1804  * shared-cache-inval notice that will make them update their partition
1805  * descriptors.
1806  */
1807  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1808  if (!HeapTupleIsValid(tuple))
1809  elog(ERROR, "cache lookup failed for relation %u", relid);
1810  if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
1811  {
1812  parentOid = get_partition_parent(relid);
1814 
1815  /*
1816  * If this is not the default partition, dropping it will change the
1817  * default partition's partition constraint, so we must lock it.
1818  */
1819  defaultPartOid = get_default_partition_oid(parentOid);
1820  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1821  LockRelationOid(defaultPartOid, AccessExclusiveLock);
1822  }
1823 
1824  ReleaseSysCache(tuple);
1825 
1826  /*
1827  * Open and lock the relation.
1828  */
1829  rel = relation_open(relid, AccessExclusiveLock);
1830 
1831  /*
1832  * There can no longer be anyone *else* touching the relation, but we
1833  * might still have open queries or cursors, or pending trigger events, in
1834  * our own session.
1835  */
1836  CheckTableNotInUse(rel, "DROP TABLE");
1837 
1838  /*
1839  * This effectively deletes all rows in the table, and may be done in a
1840  * serializable transaction. In that case we must record a rw-conflict in
1841  * to this transaction from each transaction holding a predicate lock on
1842  * the table.
1843  */
1845 
1846  /*
1847  * Delete pg_foreign_table tuple first.
1848  */
1849  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1850  {
1851  Relation rel;
1852  HeapTuple tuple;
1853 
1854  rel = heap_open(ForeignTableRelationId, RowExclusiveLock);
1855 
1857  if (!HeapTupleIsValid(tuple))
1858  elog(ERROR, "cache lookup failed for foreign table %u", relid);
1859 
1860  CatalogTupleDelete(rel, &tuple->t_self);
1861 
1862  ReleaseSysCache(tuple);
1864  }
1865 
1866  /*
1867  * If a partitioned table, delete the pg_partitioned_table tuple.
1868  */
1869  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1871 
1872  /*
1873  * If the relation being dropped is the default partition itself,
1874  * invalidate its entry in pg_partitioned_table.
1875  */
1876  if (relid == defaultPartOid)
1878 
1879  /*
1880  * Schedule unlinking of the relation's physical files at commit.
1881  */
1882  if (rel->rd_rel->relkind != RELKIND_VIEW &&
1883  rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
1884  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1885  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1886  {
1887  RelationDropStorage(rel);
1888  }
1889 
1890  /*
1891  * Close relcache entry, but *keep* AccessExclusiveLock on the relation
1892  * until transaction commit. This ensures no one else will try to do
1893  * something with the doomed relation.
1894  */
1895  relation_close(rel, NoLock);
1896 
1897  /*
1898  * Remove any associated relation synchronization states.
1899  */
1901 
1902  /*
1903  * Forget any ON COMMIT action for the rel
1904  */
1905  remove_on_commit_action(relid);
1906 
1907  /*
1908  * Flush the relation from the relcache. We want to do this before
1909  * starting to remove catalog entries, just to be certain that no relcache
1910  * entry rebuild will happen partway through. (That should not really
1911  * matter, since we don't do CommandCounterIncrement here, but let's be
1912  * safe.)
1913  */
1914  RelationForgetRelation(relid);
1915 
1916  /*
1917  * remove inheritance information
1918  */
1920 
1921  /*
1922  * delete statistics
1923  */
1924  RemoveStatistics(relid, 0);
1925 
1926  /*
1927  * delete attribute tuples
1928  */
1929  DeleteAttributeTuples(relid);
1930 
1931  /*
1932  * delete relation tuple
1933  */
1934  DeleteRelationTuple(relid);
1935 
1936  if (OidIsValid(parentOid))
1937  {
1938  /*
1939  * If this is not the default partition, the partition constraint of
1940  * the default partition has changed to include the portion of the key
1941  * space previously covered by the dropped partition.
1942  */
1943  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1944  CacheInvalidateRelcacheByRelid(defaultPartOid);
1945 
1946  /*
1947  * Invalidate the parent's relcache so that the partition is no longer
1948  * included in its partition descriptor.
1949  */
1950  CacheInvalidateRelcacheByRelid(parentOid);
1951  /* keep the lock */
1952  }
1953 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
void RemoveSubscriptionRel(Oid subid, Oid relid)
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:307
void remove_on_commit_action(Oid relid)
Definition: tablecmds.c:13206
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1270
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2595
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
Oid get_partition_parent(Oid relid)
Definition: partition.c:53
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:1300
bool relispartition
Definition: pg_class.h:69
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3222
Oid get_default_partition_oid(Oid parentId)
Definition: partition.c:282
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void RelationDropStorage(Relation rel)
Definition: storage.c:144
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define InvalidOid
Definition: postgres_ext.h:36
void DeleteRelationTuple(Oid relid)
Definition: heap.c:1445
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void RelationRemoveInheritance(Oid relid)
Definition: heap.c:1412
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4364
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1474
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:3008
FormData_pg_class * Form_pg_class
Definition: pg_class.h:93
#define AccessExclusiveLock
Definition: lockdefs.h:45
void RemovePartitionKeyByRelId(Oid relid)
Definition: heap.c:3462
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1124
#define elog
Definition: elog.h:219
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105

◆ heap_truncate()

void heap_truncate ( List relids)

Definition at line 3096 of file heap.c.

References AccessExclusiveLock, heap_close, heap_open(), heap_truncate_check_FKs(), heap_truncate_one_rel(), lappend(), lfirst, lfirst_oid, NIL, and NoLock.

Referenced by PreCommit_on_commit_actions().

3097 {
3098  List *relations = NIL;
3099  ListCell *cell;
3100 
3101  /* Open relations for processing, and grab exclusive access on each */
3102  foreach(cell, relids)
3103  {
3104  Oid rid = lfirst_oid(cell);
3105  Relation rel;
3106 
3107  rel = heap_open(rid, AccessExclusiveLock);
3108  relations = lappend(relations, rel);
3109  }
3110 
3111  /* Don't allow truncate on tables that are referenced by foreign keys */
3112  heap_truncate_check_FKs(relations, true);
3113 
3114  /* OK to do it */
3115  foreach(cell, relations)
3116  {
3117  Relation rel = lfirst(cell);
3118 
3119  /* Truncate the relation */
3120  heap_truncate_one_rel(rel);
3121 
3122  /* Close the relation, but keep exclusive lock on it until commit */
3123  heap_close(rel, NoLock);
3124  }
3125 }
#define NIL
Definition: pg_list.h:69
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:3137
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3174
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define NoLock
Definition: lockdefs.h:34
List * lappend(List *list, void *datum)
Definition: list.c:128
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define lfirst(lc)
Definition: pg_list.h:106
#define AccessExclusiveLock
Definition: lockdefs.h:45
Definition: pg_list.h:45
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ heap_truncate_check_FKs()

void heap_truncate_check_FKs ( List relations,
bool  tempTables 
)

Definition at line 3174 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, and RelationGetRelid.

Referenced by ExecuteTruncateGuts(), and heap_truncate().

3175 {
3176  List *oids = NIL;
3177  List *dependents;
3178  ListCell *cell;
3179 
3180  /*
3181  * Build a list of OIDs of the interesting relations.
3182  *
3183  * If a relation has no triggers, then it can neither have FKs nor be
3184  * referenced by a FK from another table, so we can ignore it.
3185  */
3186  foreach(cell, relations)
3187  {
3188  Relation rel = lfirst(cell);
3189 
3190  if (rel->rd_rel->relhastriggers)
3191  oids = lappend_oid(oids, RelationGetRelid(rel));
3192  }
3193 
3194  /*
3195  * Fast path: if no relation has triggers, none has FKs either.
3196  */
3197  if (oids == NIL)
3198  return;
3199 
3200  /*
3201  * Otherwise, must scan pg_constraint. We make one pass with all the
3202  * relations considered; if this finds nothing, then all is well.
3203  */
3204  dependents = heap_truncate_find_FKs(oids);
3205  if (dependents == NIL)
3206  return;
3207 
3208  /*
3209  * Otherwise we repeat the scan once per relation to identify a particular
3210  * pair of relations to complain about. This is pretty slow, but
3211  * performance shouldn't matter much in a failure path. The reason for
3212  * doing things this way is to ensure that the message produced is not
3213  * dependent on chance row locations within pg_constraint.
3214  */
3215  foreach(cell, oids)
3216  {
3217  Oid relid = lfirst_oid(cell);
3218  ListCell *cell2;
3219 
3220  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
3221 
3222  foreach(cell2, dependents)
3223  {
3224  Oid relid2 = lfirst_oid(cell2);
3225 
3226  if (!list_member_oid(oids, relid2))
3227  {
3228  char *relname = get_rel_name(relid);
3229  char *relname2 = get_rel_name(relid2);
3230 
3231  if (tempTables)
3232  ereport(ERROR,
3233  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3234  errmsg("unsupported ON COMMIT and foreign key combination"),
3235  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3236  relname2, relname)));
3237  else
3238  ereport(ERROR,
3239  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3240  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3241  errdetail("Table \"%s\" references \"%s\".",
3242  relname2, relname),
3243  errhint("Truncate table \"%s\" at the same time, "
3244  "or use TRUNCATE ... CASCADE.",
3245  relname2)));
3246  }
3247  }
3248  }
3249 }
#define NIL
Definition: pg_list.h:69
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
#define list_make1_oid(x1)
Definition: pg_list.h:151
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define lfirst(lc)
Definition: pg_list.h:106
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1730
#define RelationGetRelid(relation)
Definition: rel.h:407
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3266
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

Definition at line 3266 of file heap.c.

References AccessShareLock, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, insert_ordered_unique_oid(), InvalidOid, list_member_oid(), NIL, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by ExecuteTruncateGuts(), and heap_truncate_check_FKs().

3267 {
3268  List *result = NIL;
3269  Relation fkeyRel;
3270  SysScanDesc fkeyScan;
3271  HeapTuple tuple;
3272 
3273  /*
3274  * Must scan pg_constraint. Right now, it is a seqscan because there is
3275  * no available index on confrelid.
3276  */
3277  fkeyRel = heap_open(ConstraintRelationId, AccessShareLock);
3278 
3279  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3280  NULL, 0, NULL);
3281 
3282  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3283  {
3285 
3286  /* Not a foreign key */
3287  if (con->contype != CONSTRAINT_FOREIGN)
3288  continue;
3289 
3290  /* Not referencing one of our list of tables */
3291  if (!list_member_oid(relationIds, con->confrelid))
3292  continue;
3293 
3294  /* Add referencer unless already in input or result list */
3295  if (!list_member_oid(relationIds, con->conrelid))
3296  result = insert_ordered_unique_oid(result, con->conrelid);
3297  }
3298 
3299  systable_endscan(fkeyScan);
3300  heap_close(fkeyRel, AccessShareLock);
3301 
3302  return result;
3303 }
#define NIL
Definition: pg_list.h:69
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#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:505
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static List * insert_ordered_unique_oid(List *list, Oid datum)
Definition: heap.c:3316
Definition: pg_list.h:45

◆ heap_truncate_one_rel()

void heap_truncate_one_rel ( Relation  rel)

Definition at line 3137 of file heap.c.

References AccessExclusiveLock, heap_close, heap_open(), NoLock, OidIsValid, RelationData::rd_rel, RelationTruncate(), and RelationTruncateIndexes().

Referenced by ExecuteTruncateGuts(), and heap_truncate().

3138 {
3139  Oid toastrelid;
3140 
3141  /* Truncate the actual file (and discard buffers) */
3142  RelationTruncate(rel, 0);
3143 
3144  /* If the relation has indexes, truncate the indexes too */
3146 
3147  /* If there is a toast table, truncate that too */
3148  toastrelid = rel->rd_rel->reltoastrelid;
3149  if (OidIsValid(toastrelid))
3150  {
3151  Relation toastrel = heap_open(toastrelid, AccessExclusiveLock);
3152 
3153  RelationTruncate(toastrel, 0);
3154  RelationTruncateIndexes(toastrel);
3155  /* keep the lock... */
3156  heap_close(toastrel, NoLock);
3157  }
3158 }
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define NoLock
Definition: lockdefs.h:34
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define AccessExclusiveLock
Definition: lockdefs.h:45
static void RelationTruncateIndexes(Relation heapRelation)
Definition: heap.c:3055
void RelationTruncate(Relation rel, BlockNumber nblocks)
Definition: storage.c:226

◆ InsertPgAttributeTuple()

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

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

607 {
608  Datum values[Natts_pg_attribute];
609  bool nulls[Natts_pg_attribute];
610  HeapTuple tup;
611 
612  /* This is a tad tedious, but way cleaner than what we used to do... */
613  memset(values, 0, sizeof(values));
614  memset(nulls, false, sizeof(nulls));
615 
616  values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
617  values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
618  values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
619  values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
620  values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
621  values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
622  values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
623  values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(new_attribute->attcacheoff);
624  values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
625  values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
626  values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
627  values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
628  values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
629  values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
630  values[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(new_attribute->atthasmissing);
631  values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
632  values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
633  values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
634  values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
635  values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
636 
637  /* start out with empty permissions and empty options */
638  nulls[Anum_pg_attribute_attacl - 1] = true;
639  nulls[Anum_pg_attribute_attoptions - 1] = true;
640  nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
641  nulls[Anum_pg_attribute_attmissingval - 1] = true;
642 
643  tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
644 
645  /* finally insert the new tuple, update the indexes, and clean up */
646  if (indstate != NULL)
647  CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
648  else
649  CatalogTupleInsert(pg_attribute_rel, tup);
650 
651  heap_freetuple(tup);
652 }
#define NameGetDatum(X)
Definition: postgres.h:580
#define RelationGetDescr(relation)
Definition: rel.h:433
#define Int16GetDatum(X)
Definition: postgres.h:436
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
uintptr_t Datum
Definition: postgres.h:367
#define BoolGetDatum(X)
Definition: postgres.h:387
#define CharGetDatum(X)
Definition: postgres.h:401
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define Int32GetDatum(X)
Definition: postgres.h:464
Oid CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:187

◆ InsertPgClassTuple()

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

Definition at line 772 of file heap.c.

References BoolGetDatum, CatalogTupleInsert(), CharGetDatum, Float4GetDatum(), heap_form_tuple(), heap_freetuple(), HeapTupleSetOid, Int16GetDatum, Int32GetDatum, MultiXactIdGetDatum, NameGetDatum, ObjectIdGetDatum, RelationData::rd_rel, RelationGetDescr, TransactionIdGetDatum, and values.

Referenced by AddNewRelationTuple(), and index_create().

777 {
778  Form_pg_class rd_rel = new_rel_desc->rd_rel;
779  Datum values[Natts_pg_class];
780  bool nulls[Natts_pg_class];
781  HeapTuple tup;
782 
783  /* This is a tad tedious, but way cleaner than what we used to do... */
784  memset(values, 0, sizeof(values));
785  memset(nulls, false, sizeof(nulls));
786 
787  values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
788  values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
789  values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
790  values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
791  values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
792  values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
793  values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
794  values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
795  values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
796  values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
797  values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
798  values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
799  values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
800  values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
801  values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
802  values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
803  values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
804  values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
805  values[Anum_pg_class_relhasoids - 1] = BoolGetDatum(rd_rel->relhasoids);
806  values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
807  values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
808  values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
809  values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
810  values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
811  values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
812  values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
813  values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
814  values[Anum_pg_class_relrewrite - 1] = ObjectIdGetDatum(rd_rel->relrewrite);
815  values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
816  values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
817  if (relacl != (Datum) 0)
818  values[Anum_pg_class_relacl - 1] = relacl;
819  else
820  nulls[Anum_pg_class_relacl - 1] = true;
821  if (reloptions != (Datum) 0)
822  values[Anum_pg_class_reloptions - 1] = reloptions;
823  else
824  nulls[Anum_pg_class_reloptions - 1] = true;
825 
826  /* relpartbound is set by updating this tuple, if necessary */
827  nulls[Anum_pg_class_relpartbound - 1] = true;
828 
829  tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
830 
831  /*
832  * The new tuple must have the oid already chosen for the rel. Sure would
833  * be embarrassing to do this sort of thing in polite company.
834  */
835  HeapTupleSetOid(tup, new_rel_oid);
836 
837  /* finally insert the new tuple, update the indexes, and clean up */
838  CatalogTupleInsert(pg_class_desc, tup);
839 
840  heap_freetuple(tup);
841 }
#define NameGetDatum(X)
Definition: postgres.h:580
#define MultiXactIdGetDatum(X)
Definition: postgres.h:513
#define RelationGetDescr(relation)
Definition: rel.h:433
#define Int16GetDatum(X)
Definition: postgres.h:436
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
Form_pg_class rd_rel
Definition: rel.h:84
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:710
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
Datum Float4GetDatum(float4 X)
Definition: fmgr.c:1889
#define TransactionIdGetDatum(X)
Definition: postgres.h:506
uintptr_t Datum
Definition: postgres.h:367
#define BoolGetDatum(X)
Definition: postgres.h:387
#define CharGetDatum(X)
Definition: postgres.h:401
static Datum values[MAXATTR]
Definition: bootstrap.c:164
FormData_pg_class * Form_pg_class
Definition: pg_class.h:93
#define Int32GetDatum(X)
Definition: postgres.h:464

◆ RelationClearMissing()

void RelationClearMissing ( Relation  rel)

Definition at line 1967 of file heap.c.

References ATTNUM, attnum, BoolGetDatum, CatalogTupleUpdate(), elog, ERROR, GETSTRUCT, heap_close, heap_freetuple(), heap_modify_tuple(), heap_open(), HeapTupleIsValid, Int16GetDatum, ObjectIdGetDatum, RelationGetDescr, RelationGetNumberOfAttributes, RelationGetRelid, ReleaseSysCache(), RowExclusiveLock, SearchSysCache2(), and HeapTupleData::t_self.

Referenced by finish_heap_swap().

1968 {
1969  Relation attr_rel;
1970  Oid relid = RelationGetRelid(rel);
1971  int natts = RelationGetNumberOfAttributes(rel);
1972  int attnum;
1973  Datum repl_val[Natts_pg_attribute];
1974  bool repl_null[Natts_pg_attribute];
1975  bool repl_repl[Natts_pg_attribute];
1976  Form_pg_attribute attrtuple;
1977  HeapTuple tuple,
1978  newtuple;
1979 
1980  memset(repl_val, 0, sizeof(repl_val));
1981  memset(repl_null, false, sizeof(repl_null));
1982  memset(repl_repl, false, sizeof(repl_repl));
1983 
1984  repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
1985  repl_null[Anum_pg_attribute_attmissingval - 1] = true;
1986 
1987  repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
1988  repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
1989 
1990 
1991  /* Get a lock on pg_attribute */
1992  attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
1993 
1994  /* process each non-system attribute, including any dropped columns */
1995  for (attnum = 1; attnum <= natts; attnum++)
1996  {
1997  tuple = SearchSysCache2(ATTNUM,
1998  ObjectIdGetDatum(relid),
1999  Int16GetDatum(attnum));
2000  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
2001  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2002  attnum, relid);
2003 
2004  attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
2005 
2006  /* ignore any where atthasmissing is not true */
2007  if (attrtuple->atthasmissing)
2008  {
2009  newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
2010  repl_val, repl_null, repl_repl);
2011 
2012  CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
2013 
2014  heap_freetuple(newtuple);
2015  }
2016 
2017  ReleaseSysCache(tuple);
2018  }
2019 
2020  /*
2021  * Our update of the pg_attribute rows will force a relcache rebuild, so
2022  * there's nothing else to do here.
2023  */
2024  heap_close(attr_rel, RowExclusiveLock);
2025 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define RelationGetDescr(relation)
Definition: rel.h:433
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:413
#define Int16GetDatum(X)
Definition: postgres.h:436
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#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:197
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define BoolGetDatum(X)
Definition: postgres.h:387
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:211
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1123
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
#define RelationGetRelid(relation)
Definition: rel.h:407

◆ RemoveAttrDefault()

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

Definition at line 1663 of file heap.c.

References AttrDefaultIndexId, BTEqualStrategyNumber, ObjectAddress::classId, elog, ERROR, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, Int16GetDatum, ObjectAddressStack::object, ObjectIdGetDatum, PERFORM_DELETION_INTERNAL, performDeletion(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by ATExecAlterColumnType(), and ATExecColumnDefault().

1665 {
1666  Relation attrdef_rel;
1667  ScanKeyData scankeys[2];
1668  SysScanDesc scan;
1669  HeapTuple tuple;
1670  bool found = false;
1671 
1672  attrdef_rel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
1673 
1674  ScanKeyInit(&scankeys[0],
1675  Anum_pg_attrdef_adrelid,
1676  BTEqualStrategyNumber, F_OIDEQ,
1677  ObjectIdGetDatum(relid));
1678  ScanKeyInit(&scankeys[1],
1679  Anum_pg_attrdef_adnum,
1680  BTEqualStrategyNumber, F_INT2EQ,
1682 
1683  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1684  NULL, 2, scankeys);
1685 
1686  /* There should be at most one matching tuple, but we loop anyway */
1687  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1688  {
1689  ObjectAddress object;
1690 
1691  object.classId = AttrDefaultRelationId;
1692  object.objectId = HeapTupleGetOid(tuple);
1693  object.objectSubId = 0;
1694 
1695  performDeletion(&object, behavior,
1696  internal ? PERFORM_DELETION_INTERNAL : 0);
1697 
1698  found = true;
1699  }
1700 
1701  systable_endscan(scan);
1702  heap_close(attrdef_rel, RowExclusiveLock);
1703 
1704  if (complain && !found)
1705  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1706  relid, attnum);
1707 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define Int16GetDatum(X)
Definition: postgres.h:436
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
#define AttrDefaultIndexId
Definition: indexing.h:86
#define RowExclusiveLock
Definition: lockdefs.h:38
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:300
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:707
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:189

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

Definition at line 1717 of file heap.c.

References AccessExclusiveLock, ATTNUM, AttrDefaultOidIndexId, BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), elog, ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, Int16GetDatum, NoLock, ObjectIdAttributeNumber, ObjectIdGetDatum, relation_close(), relation_open(), RowExclusiveLock, ScanKeyInit(), SearchSysCacheCopy2, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by doDeletion().

1718 {
1719  Relation attrdef_rel;
1720  Relation attr_rel;
1721  Relation myrel;
1722  ScanKeyData scankeys[1];
1723  SysScanDesc scan;
1724  HeapTuple tuple;
1725  Oid myrelid;
1726  AttrNumber myattnum;
1727 
1728  /* Grab an appropriate lock on the pg_attrdef relation */
1729  attrdef_rel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
1730 
1731  /* Find the pg_attrdef tuple */
1732  ScanKeyInit(&scankeys[0],
1734  BTEqualStrategyNumber, F_OIDEQ,
1735  ObjectIdGetDatum(attrdefId));
1736 
1737  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1738  NULL, 1, scankeys);
1739 
1740  tuple = systable_getnext(scan);
1741  if (!HeapTupleIsValid(tuple))
1742  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1743 
1744  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1745  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1746 
1747  /* Get an exclusive lock on the relation owning the attribute */
1748  myrel = relation_open(myrelid, AccessExclusiveLock);
1749 
1750  /* Now we can delete the pg_attrdef row */
1751  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1752 
1753  systable_endscan(scan);
1754  heap_close(attrdef_rel, RowExclusiveLock);
1755 
1756  /* Fix the pg_attribute row */
1757  attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
1758 
1759  tuple = SearchSysCacheCopy2(ATTNUM,
1760  ObjectIdGetDatum(myrelid),
1761  Int16GetDatum(myattnum));
1762  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1763  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1764  myattnum, myrelid);
1765 
1766  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1767 
1768  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1769 
1770  /*
1771  * Our update of the pg_attribute row will force a relcache rebuild, so
1772  * there's nothing else to do here.
1773  */
1774  heap_close(attr_rel, RowExclusiveLock);
1775 
1776  /* Keep lock on attribute's rel until end of xact */
1777  relation_close(myrel, NoLock);
1778 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define Int16GetDatum(X)
Definition: postgres.h:436
#define AttrDefaultOidIndexId
Definition: indexing.h:88
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1270
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
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:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
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:197
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:45
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
#define AccessExclusiveLock
Definition: lockdefs.h:45
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1124
#define elog
Definition: elog.h:219
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:175
int16 AttrNumber
Definition: attnum.h:21
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RemoveAttributeById()

void RemoveAttributeById ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 1552 of file heap.c.

References AccessExclusiveLock, ATTNUM, BoolGetDatum, CatalogTupleDelete(), CatalogTupleUpdate(), elog, ERROR, GETSTRUCT, heap_close, heap_modify_tuple(), heap_open(), HeapTupleIsValid, Int16GetDatum, InvalidOid, MemSet, NAMEDATALEN, namestrcpy(), NoLock, ObjectIdGetDatum, relation_close(), relation_open(), RelationGetDescr, RemoveStatistics(), RowExclusiveLock, SearchSysCacheCopy2, snprintf(), and HeapTupleData::t_self.

Referenced by doDeletion().

1553 {
1554  Relation rel;
1555  Relation attr_rel;
1556  HeapTuple tuple;
1557  Form_pg_attribute attStruct;
1558  char newattname[NAMEDATALEN];
1559 
1560  /*
1561  * Grab an exclusive lock on the target table, which we will NOT release
1562  * until end of transaction. (In the simple case where we are directly
1563  * dropping this column, AlterTableDropColumn already did this ... but
1564  * when cascading from a drop of some other object, we may not have any
1565  * lock.)
1566  */
1567  rel = relation_open(relid, AccessExclusiveLock);
1568 
1569  attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
1570 
1571  tuple = SearchSysCacheCopy2(ATTNUM,
1572  ObjectIdGetDatum(relid),
1574  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1575  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1576  attnum, relid);
1577  attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
1578 
1579  if (attnum < 0)
1580  {
1581  /* System attribute (probably OID) ... just delete the row */
1582 
1583  CatalogTupleDelete(attr_rel, &tuple->t_self);
1584  }
1585  else
1586  {
1587  /* Dropping user attributes is lots harder */
1588 
1589  /* Mark the attribute as dropped */
1590  attStruct->attisdropped = true;
1591 
1592  /*
1593  * Set the type OID to invalid. A dropped attribute's type link
1594  * cannot be relied on (once the attribute is dropped, the type might
1595  * be too). Fortunately we do not need the type row --- the only
1596  * really essential information is the type's typlen and typalign,
1597  * which are preserved in the attribute's attlen and attalign. We set
1598  * atttypid to zero here as a means of catching code that incorrectly
1599  * expects it to be valid.
1600  */
1601  attStruct->atttypid = InvalidOid;
1602 
1603  /* Remove any NOT NULL constraint the column may have */
1604  attStruct->attnotnull = false;
1605 
1606  /* We don't want to keep stats for it anymore */
1607  attStruct->attstattarget = 0;
1608 
1609  /*
1610  * Change the column name to something that isn't likely to conflict
1611  */
1612  snprintf(newattname, sizeof(newattname),
1613  "........pg.dropped.%d........", attnum);
1614  namestrcpy(&(attStruct->attname), newattname);
1615 
1616  /* clear the missing value if any */
1617  if (attStruct->atthasmissing)
1618  {
1619  Datum valuesAtt[Natts_pg_attribute];
1620  bool nullsAtt[Natts_pg_attribute];
1621  bool replacesAtt[Natts_pg_attribute];
1622 
1623  /* update the tuple - set atthasmissing and attmissingval */
1624  MemSet(valuesAtt, 0, sizeof(valuesAtt));
1625  MemSet(nullsAtt, false, sizeof(nullsAtt));
1626  MemSet(replacesAtt, false, sizeof(replacesAtt));
1627 
1628  valuesAtt[Anum_pg_attribute_atthasmissing - 1] =
1629  BoolGetDatum(false);
1630  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
1631  valuesAtt[Anum_pg_attribute_attmissingval - 1] = (Datum) 0;
1632  nullsAtt[Anum_pg_attribute_attmissingval - 1] = true;
1633  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
1634 
1635  tuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
1636  valuesAtt, nullsAtt, replacesAtt);
1637  }
1638 
1639  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1640  }
1641 
1642  /*
1643  * Because updating the pg_attribute row will trigger a relcache flush for
1644  * the target relation, we need not do anything else to notify other
1645  * backends of the change.
1646  */
1647 
1648  heap_close(attr_rel, RowExclusiveLock);
1649 
1650  if (attnum > 0)
1651  RemoveStatistics(relid, attnum);
1652 
1653  relation_close(rel, NoLock);
1654 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define RelationGetDescr(relation)
Definition: rel.h:433
#define Int16GetDatum(X)
Definition: postgres.h:436
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1270
#define MemSet(start, val, len)
Definition: c.h:908
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
int namestrcpy(Name name, const char *str)
Definition: name.c:216
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
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:197
uintptr_t Datum
Definition: postgres.h:367
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define BoolGetDatum(X)
Definition: postgres.h:387
#define InvalidOid
Definition: postgres_ext.h:36
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:211
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:3008
#define AccessExclusiveLock
Definition: lockdefs.h:45
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1124
#define elog
Definition: elog.h:219
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:175
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

Definition at line 3462 of file heap.c.

References CatalogTupleDelete(), elog, ERROR, heap_close, heap_open(), HeapTupleIsValid, ObjectIdGetDatum, PARTRELID, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), and HeapTupleData::t_self.

Referenced by heap_drop_with_catalog().

3463 {
3464  Relation rel;
3465  HeapTuple tuple;
3466 
3467  rel = heap_open(PartitionedRelationId, RowExclusiveLock);
3468 
3469  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3470  if (!HeapTupleIsValid(tuple))
3471  elog(ERROR, "cache lookup failed for partition key of relation %u",
3472  relid);
3473 
3474  CatalogTupleDelete(rel, &tuple->t_self);
3475 
3476  ReleaseSysCache(tuple);
3478 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#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:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog
Definition: elog.h:219

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 3008 of file heap.c.

References BTEqualStrategyNumber, CatalogTupleDelete(), heap_close, heap_open(), HeapTupleIsValid, Int16GetDatum, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), StatisticRelidAttnumInhIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by ATExecAlterColumnType(), heap_drop_with_catalog(), index_drop(), and RemoveAttributeById().

3009 {
3010  Relation pgstatistic;
3011  SysScanDesc scan;
3012  ScanKeyData key[2];
3013  int nkeys;
3014  HeapTuple tuple;
3015 
3016  pgstatistic = heap_open(StatisticRelationId, RowExclusiveLock);
3017 
3018  ScanKeyInit(&key[0],
3019  Anum_pg_statistic_starelid,
3020  BTEqualStrategyNumber, F_OIDEQ,
3021  ObjectIdGetDatum(relid));
3022 
3023  if (attnum == 0)
3024  nkeys = 1;
3025  else
3026  {
3027  ScanKeyInit(&key[1],
3028  Anum_pg_statistic_staattnum,
3029  BTEqualStrategyNumber, F_INT2EQ,
3031  nkeys = 2;
3032  }
3033 
3034  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
3035  NULL, nkeys, key);
3036 
3037  /* we must loop even when attnum != 0, in case of inherited stats */
3038  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
3039  CatalogTupleDelete(pgstatistic, &tuple->t_self);
3040 
3041  systable_endscan(scan);
3042 
3043  heap_close(pgstatistic, RowExclusiveLock);
3044 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define Int16GetDatum(X)
Definition: postgres.h:436
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:256
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:331
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:419
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define StatisticRelidAttnumInhIndexId
Definition: indexing.h:235
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ SetAttrMissing()

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

Definition at line 2035 of file heap.c.

References AccessExclusiveLock, BoolGetDatum, CatalogTupleUpdate(), CStringGetDatum, elog, ERROR, GETSTRUCT, heap_close, heap_modify_tuple(), heap_open(), HeapTupleIsValid, Int32GetDatum, MemSet, ObjectIdGetDatum, OidFunctionCall3, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCacheAttName(), and HeapTupleData::t_self.

Referenced by binary_upgrade_set_missing_value().

2036 {
2037  Datum valuesAtt[Natts_pg_attribute];
2038  bool nullsAtt[Natts_pg_attribute];
2039  bool replacesAtt[Natts_pg_attribute];
2040  Datum missingval;
2041  Form_pg_attribute attStruct;
2042  Relation attrrel,
2043  tablerel;
2044  HeapTuple atttup,
2045  newtup;
2046 
2047  /* lock the table the attribute belongs to */
2048  tablerel = heap_open(relid, AccessExclusiveLock);
2049 
2050  /* Lock the attribute row and get the data */
2051  attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
2052  atttup = SearchSysCacheAttName(relid, attname);
2053  if (!HeapTupleIsValid(atttup))
2054  elog(ERROR, "cache lookup failed for attribute %s of relation %u",
2055  attname, relid);
2056  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2057 
2058  /* get an array value from the value string */
2059  missingval = OidFunctionCall3(F_ARRAY_IN,
2061  ObjectIdGetDatum(attStruct->atttypid),
2062  Int32GetDatum(attStruct->atttypmod));
2063 
2064  /* update the tuple - set atthasmissing and attmissingval */
2065  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2066  MemSet(nullsAtt, false, sizeof(nullsAtt));
2067  MemSet(replacesAtt, false, sizeof(replacesAtt));
2068 
2069  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(true);
2070  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2071  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2072  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2073 
2074  newtup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2075  valuesAtt, nullsAtt, replacesAtt);
2076  CatalogTupleUpdate(attrrel, &newtup->t_self, newtup);
2077 
2078  /* clean up */
2079  ReleaseSysCache(atttup);
2080  heap_close(attrrel, RowExclusiveLock);
2081  heap_close(tablerel, AccessExclusiveLock);
2082 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define RelationGetDescr(relation)
Definition: rel.h:433
#define MemSet(start, val, len)
Definition: c.h:908
#define heap_close(r, l)
Definition: heapam.h:97
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#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:563
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
#define OidFunctionCall3(functionId, arg1, arg2, arg3)
Definition: fmgr.h:632
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
static struct @131 value
#define BoolGetDatum(X)
Definition: postgres.h:387
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1248
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define Int32GetDatum(X)
Definition: postgres.h:464
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173

◆ StoreAttrDefault()

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

Definition at line 2096 of file heap.c.

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

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

2098 {
2099  char *adbin;
2100  char *adsrc;
2101  Relation adrel;
2102  HeapTuple tuple;
2103  Datum values[4];
2104  static bool nulls[4] = {false, false, false, false};
2105  Relation attrrel;
2106  HeapTuple atttup;
2107  Form_pg_attribute attStruct;
2108  Oid attrdefOid;
2109  ObjectAddress colobject,
2110  defobject;
2111 
2112  /*
2113  * Flatten expression to string form for storage.
2114  */
2115  adbin = nodeToString(expr);
2116 
2117  /*
2118  * Also deparse it to form the mostly-obsolete adsrc field.
2119  */
2120  adsrc = deparse_expression(expr,
2122  RelationGetRelid(rel)),
2123  false, false);
2124 
2125  /*
2126  * Make the pg_attrdef entry.
2127  */
2128  values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
2129  values[Anum_pg_attrdef_adnum - 1] = attnum;
2130  values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
2131  values[Anum_pg_attrdef_adsrc - 1] = CStringGetTextDatum(adsrc);
2132 
2133  adrel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
2134 
2135  tuple = heap_form_tuple(adrel->rd_att, values, nulls);
2136  attrdefOid = CatalogTupleInsert(adrel, tuple);
2137 
2138  defobject.classId = AttrDefaultRelationId;
2139  defobject.objectId = attrdefOid;
2140  defobject.objectSubId = 0;
2141 
2142  heap_close(adrel, RowExclusiveLock);
2143 
2144  /* now can free some of the stuff allocated above */
2145  pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
2146  pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
2147  heap_freetuple(tuple);
2148  pfree(adbin);
2149  pfree(adsrc);
2150 
2151  /*
2152  * Update the pg_attribute entry for the column to show that a default
2153  * exists.
2154  */
2155  attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
2156  atttup = SearchSysCacheCopy2(ATTNUM,
2159  if (!HeapTupleIsValid(atttup))
2160  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2161  attnum, RelationGetRelid(rel));
2162  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2163  if (!attStruct->atthasdef)
2164  {
2165  Form_pg_attribute defAttStruct;
2166 
2167  ExprState *exprState;
2168  Expr *expr2 = (Expr *) expr;
2169  EState *estate = NULL;
2170  ExprContext *econtext;
2171  Datum valuesAtt[Natts_pg_attribute];
2172  bool nullsAtt[Natts_pg_attribute];
2173  bool replacesAtt[Natts_pg_attribute];
2174  Datum missingval = (Datum) 0;
2175  bool missingIsNull = true;
2176 
2177  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2178  MemSet(nullsAtt, false, sizeof(nullsAtt));
2179  MemSet(replacesAtt, false, sizeof(replacesAtt));
2180  valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2181  replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2182 
2183  if (add_column_mode)
2184  {
2185  expr2 = expression_planner(expr2);
2186  estate = CreateExecutorState();
2187  exprState = ExecPrepareExpr(expr2, estate);
2188  econtext = GetPerTupleExprContext(estate);
2189 
2190  missingval = ExecEvalExpr(exprState, econtext,
2191  &missingIsNull);
2192 
2193  FreeExecutorState(estate);
2194 
2195  defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1);
2196 
2197  if (missingIsNull)
2198  {
2199  /* if the default evaluates to NULL, just store a NULL array */
2200  missingval = (Datum) 0;
2201  }
2202  else
2203  {
2204  /* otherwise make a one-element array of the value */
2205  missingval = PointerGetDatum(
2206  construct_array(&missingval,
2207  1,
2208  defAttStruct->atttypid,
2209  defAttStruct->attlen,
2210  defAttStruct->attbyval,
2211  defAttStruct->attalign));
2212  }
2213 
2214  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
2215  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2216  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2217  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2218  nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull;
2219  }
2220  atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2221  valuesAtt, nullsAtt, replacesAtt);
2222 
2223  CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
2224 
2225  if (!missingIsNull)
2226  pfree(DatumGetPointer(missingval));
2227 
2228  }
2229  heap_close(attrrel, RowExclusiveLock);
2230  heap_freetuple(atttup);
2231 
2232  /*
2233  * Make a dependency so that the pg_attrdef entry goes away if the column
2234  * (or whole table) is deleted.
2235  */
2236  colobject.classId = RelationRelationId;
2237  colobject.objectId = RelationGetRelid(rel);
2238  colobject.objectSubId = attnum;
2239 
2240  recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
2241 
2242  /*
2243  * Record dependencies on objects used in the expression, too.
2244  */
2245  recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
2246 
2247  /*
2248  * Post creation hook for attribute defaults.
2249  *
2250  * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
2251  * couple of deletion/creation of the attribute's default entry, so the
2252  * callee should check existence of an older version of this entry if it
2253  * needs to distinguish.
2254  */
2255  InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
2256  RelationGetRelid(rel), attnum, is_internal);
2257 
2258  return attrdefOid;
2259 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define RelationGetDescr(relation)
Definition: rel.h:433
#define PointerGetDatum(X)
Definition: postgres.h:541
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
Expr * expression_planner(Expr *expr)
Definition: planner.c:5888
#define Int16GetDatum(X)
Definition: postgres.h:436
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3279
#define MemSet(start, val, len)
Definition: c.h:908
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:488
void FreeExecutorState(EState *estate)
Definition: execUtils.c:188
#define GetPerTupleExprContext(estate)
Definition: executor.h:488
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
ItemPointerData t_self
Definition: htup.h:65
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:280
#define RowExclusiveLock
Definition: lockdefs.h:38
List * deparse_context_for(const char *aliasname, Oid relid)
Definition: ruleutils.c:3130
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1360
#define RelationGetRelationName(relation)
Definition: rel.h:441
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
EState * CreateExecutorState(void)
Definition: execUtils.c:80
uintptr_t Datum
Definition: postgres.h:367
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:147
TupleDesc rd_att
Definition: rel.h:85
int16 attnum
Definition: pg_attribute.h:79
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition: ruleutils.c:3071
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
#define DatumGetPointer(X)
Definition: postgres.h:534
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define CStringGetTextDatum(s)
Definition: builtins.h:95
char * nodeToString(const void *obj)
Definition: outfuncs.c:4339
#define elog
Definition: elog.h:219
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:175
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
#define RelationGetRelid(relation)
Definition: rel.h:407

◆ StorePartitionBound()

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

Definition at line 3493 of file heap.c.

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

Referenced by ATExecAttachPartition(), and DefineRelation().

3494 {
3495  Relation classRel;
3496  HeapTuple tuple,
3497  newtuple;
3498  Datum new_val[Natts_pg_class];
3499  bool new_null[Natts_pg_class],
3500  new_repl[Natts_pg_class];
3501  Oid defaultPartOid;
3502 
3503  /* Update pg_class tuple */
3504  classRel = heap_open(RelationRelationId, RowExclusiveLock);
3505  tuple = SearchSysCacheCopy1(RELOID,
3507  if (!HeapTupleIsValid(tuple))
3508  elog(ERROR, "cache lookup failed for relation %u",
3509  RelationGetRelid(rel));
3510 
3511 #ifdef USE_ASSERT_CHECKING
3512  {
3513  Form_pg_class classForm;
3514  bool isnull;
3515 
3516  classForm = (Form_pg_class) GETSTRUCT(tuple);
3517  Assert(!classForm->relispartition);
3518  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3519  &isnull);
3520  Assert(isnull);
3521  }
3522 #endif
3523 
3524  /* Fill in relpartbound value */
3525  memset(new_val, 0, sizeof(new_val));
3526  memset(new_null, false, sizeof(new_null));
3527  memset(new_repl, false, sizeof(new_repl));
3528  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3529  new_null[Anum_pg_class_relpartbound - 1] = false;
3530  new_repl[Anum_pg_class_relpartbound - 1] = true;
3531  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3532  new_val, new_null, new_repl);
3533  /* Also set the flag */
3534  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3535  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3536  heap_freetuple(newtuple);
3537  heap_close(classRel, RowExclusiveLock);
3538 
3539  /*
3540  * If we're storing bounds for the default partition, update
3541  * pg_partitioned_table too.
3542  */
3543  if (bound->is_default)
3545  RelationGetRelid(rel));
3546 
3547  /* Make these updates visible */
3549 
3550  /*
3551  * The partition constraint for the default partition depends on the
3552  * partition bounds of every other partition, so we must invalidate the
3553  * relcache entry for that partition every time a partition is added or
3554  * removed.
3555  */
3556  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3557  if (OidIsValid(defaultPartOid))
3558  CacheInvalidateRelcacheByRelid(defaultPartOid);
3559 
3560  CacheInvalidateRelcache(parent);
3561 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define RelationGetDescr(relation)
Definition: rel.h:433
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:307
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1300
bool relispartition
Definition: pg_class.h:69
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:914
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1241
FormData_pg_class * Form_pg_class
Definition: pg_class.h:93
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define CStringGetTextDatum(s)
Definition: builtins.h:95
char * nodeToString(const void *obj)
Definition: outfuncs.c:4339
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1173
#define RelationGetRelid(relation)
Definition: rel.h:407
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
Definition: partition.c:265
#define RelationGetPartitionDesc(relation)
Definition: rel.h:595

◆ StorePartitionKey()

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

Definition at line 3350 of file heap.c.

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

Referenced by DefineRelation().

3357 {
3358  int i;
3359  int2vector *partattrs_vec;
3360  oidvector *partopclass_vec;
3361  oidvector *partcollation_vec;
3362  Datum partexprDatum;
3363  Relation pg_partitioned_table;
3364  HeapTuple tuple;
3365  Datum values[Natts_pg_partitioned_table];
3366  bool nulls[Natts_pg_partitioned_table];
3367  ObjectAddress myself;
3368  ObjectAddress referenced;
3369 
3370  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3371 
3372  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3373  partattrs_vec = buildint2vector(partattrs, partnatts);
3374  partopclass_vec = buildoidvector(partopclass, partnatts);
3375  partcollation_vec = buildoidvector(partcollation, partnatts);
3376 
3377  /* Convert the expressions (if any) to a text datum */
3378  if (partexprs)
3379  {
3380  char *exprString;
3381 
3382  exprString = nodeToString(partexprs);
3383  partexprDatum = CStringGetTextDatum(exprString);
3384  pfree(exprString);
3385  }
3386  else
3387  partexprDatum = (Datum) 0;
3388 
3389  pg_partitioned_table = heap_open(PartitionedRelationId, RowExclusiveLock);
3390 
3391  MemSet(nulls, false, sizeof(nulls));
3392 
3393  /* Only this can ever be NULL */
3394  if (!partexprDatum)
3395  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3396 
3397  values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
3398  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3399  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3400  values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
3401  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3402  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3403  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3404  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3405 
3406  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3407 
3408  CatalogTupleInsert(pg_partitioned_table, tuple);
3409  heap_close(pg_partitioned_table, RowExclusiveLock);
3410 
3411  /* Mark this relation as dependent on a few things as follows */
3412  myself.classId = RelationRelationId;
3413  myself.objectId = RelationGetRelid(rel);;
3414  myself.objectSubId = 0;
3415 
3416  /* Operator class and collation per key column */
3417  for (i = 0; i < partnatts; i++)
3418  {
3419  referenced.classId = OperatorClassRelationId;
3420  referenced.objectId = partopclass[i];
3421  referenced.objectSubId = 0;
3422 
3423  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3424 
3425  /* The default collation is pinned, so don't bother recording it */
3426  if (OidIsValid(partcollation[i]) &&
3427  partcollation[i] != DEFAULT_COLLATION_OID)
3428  {
3429  referenced.classId = CollationRelationId;
3430  referenced.objectId = partcollation[i];
3431  referenced.objectSubId = 0;
3432  }
3433 
3434  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3435  }
3436 
3437  /*
3438  * Anything mentioned in the expressions. We must ignore the column
3439  * references, which will depend on the table itself; there is no separate
3440  * partition key object.
3441  */
3442  if (partexprs)
3444  (Node *) partexprs,
3445  RelationGetRelid(rel),
3447  DEPENDENCY_AUTO, true);
3448 
3449  /*
3450  * We must invalidate the relcache so that the next
3451  * CommandCounterIncrement() will cause the same to be rebuilt using the
3452  * information in just created catalog entry.
3453  */
3455 }
Definition: c.h:555
#define RelationGetDescr(relation)
Definition: rel.h:433
#define PointerGetDatum(X)
Definition: postgres.h:541
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:110
#define Int16GetDatum(X)
Definition: postgres.h:436
Definition: nodes.h:516
#define MemSet(start, val, len)
Definition: c.h:908
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:84
#define OidIsValid(objectId)
Definition: c.h:605
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
#define RowExclusiveLock
Definition: lockdefs.h:38
Definition: c.h:544
uintptr_t Datum
Definition: postgres.h:367
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:699
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 ignore_self)
Definition: dependency.c:1401
#define CharGetDatum(X)
Definition: postgres.h:401
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1241
static Datum values[MAXATTR]
Definition: bootstrap.c:164
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:95
char * nodeToString(const void *obj)
Definition: outfuncs.c:4339
#define RelationGetRelid(relation)
Definition: rel.h:407

◆ SystemAttributeByName()

Form_pg_attribute SystemAttributeByName ( const char *  attname,
bool  relhasoids 
)

Definition at line 217 of file heap.c.

References lengthof, NameStr, ObjectIdAttributeNumber, and SysAtt.

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

218 {
219  int j;
220 
221  for (j = 0; j < (int) lengthof(SysAtt); j++)
222  {
223  Form_pg_attribute att = SysAtt[j];
224 
225  if (relhasoids || att->attnum != ObjectIdAttributeNumber)
226  {
227  if (strcmp(NameStr(att->attname), attname) == 0)
228  return att;
229  }
230  }
231 
232  return NULL;
233 }
bool relhasoids
Definition: pg_class.h:60
static const Form_pg_attribute SysAtt[]
Definition: heap.c:195
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define lengthof(array)
Definition: c.h:629
NameData attname
Definition: pg_attribute.h:40
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
#define NameStr(name)
Definition: c.h:576

◆ SystemAttributeDefinition()

Form_pg_attribute SystemAttributeDefinition ( AttrNumber  attno,
bool  relhasoids 
)

Definition at line 203 of file heap.c.

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

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

204 {
205  if (attno >= 0 || attno < -(int) lengthof(SysAtt))
206  elog(ERROR, "invalid system attribute number %d", attno);
207  if (attno == ObjectIdAttributeNumber && !relhasoids)
208  elog(ERROR, "invalid system attribute number %d", attno);
209  return SysAtt[-attno - 1];
210 }
bool relhasoids
Definition: pg_class.h:60
static const Form_pg_attribute SysAtt[]
Definition: heap.c:195
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define lengthof(array)
Definition: c.h:629
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219