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)
 
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 2379 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().

2385 {
2386  List *cookedConstraints = NIL;
2388  TupleConstr *oldconstr;
2389  int numoldchecks;
2390  ParseState *pstate;
2391  RangeTblEntry *rte;
2392  int numchecks;
2393  List *checknames;
2394  ListCell *cell;
2395  Node *expr;
2396  CookedConstraint *cooked;
2397 
2398  /*
2399  * Get info about existing constraints.
2400  */
2401  tupleDesc = RelationGetDescr(rel);
2402  oldconstr = tupleDesc->constr;
2403  if (oldconstr)
2404  numoldchecks = oldconstr->num_check;
2405  else
2406  numoldchecks = 0;
2407 
2408  /*
2409  * Create a dummy ParseState and insert the target relation as its sole
2410  * rangetable entry. We need a ParseState for transformExpr.
2411  */
2412  pstate = make_parsestate(NULL);
2413  rte = addRangeTableEntryForRelation(pstate,
2414  rel,
2415  NULL,
2416  false,
2417  true);
2418  addRTEtoQuery(pstate, rte, true, true, true);
2419 
2420  /*
2421  * Process column default expressions.
2422  */
2423  foreach(cell, newColDefaults)
2424  {
2425  RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
2426  Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
2427  Oid defOid;
2428 
2429  expr = cookDefault(pstate, colDef->raw_default,
2430  atp->atttypid, atp->atttypmod,
2431  NameStr(atp->attname));
2432 
2433  /*
2434  * If the expression is just a NULL constant, we do not bother to make
2435  * an explicit pg_attrdef entry, since the default behavior is
2436  * equivalent.
2437  *
2438  * Note a nonobvious property of this test: if the column is of a
2439  * domain type, what we'll get is not a bare null Const but a
2440  * CoerceToDomain expr, so we will not discard the default. This is
2441  * critical because the column default needs to be retained to
2442  * override any default that the domain might have.
2443  */
2444  if (expr == NULL ||
2445  (IsA(expr, Const) &&((Const *) expr)->constisnull))
2446  continue;
2447 
2448  /* If the DEFAULT is volatile we cannot use a missing value */
2449  if (colDef->missingMode && contain_volatile_functions((Node *) expr))
2450  colDef->missingMode = false;
2451 
2452  defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal,
2453  colDef->missingMode);
2454 
2455  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2456  cooked->contype = CONSTR_DEFAULT;
2457  cooked->conoid = defOid;
2458  cooked->name = NULL;
2459  cooked->attnum = colDef->attnum;
2460  cooked->expr = expr;
2461  cooked->skip_validation = false;
2462  cooked->is_local = is_local;
2463  cooked->inhcount = is_local ? 0 : 1;
2464  cooked->is_no_inherit = false;
2465  cookedConstraints = lappend(cookedConstraints, cooked);
2466  }
2467 
2468  /*
2469  * Process constraint expressions.
2470  */
2471  numchecks = numoldchecks;
2472  checknames = NIL;
2473  foreach(cell, newConstraints)
2474  {
2475  Constraint *cdef = (Constraint *) lfirst(cell);
2476  char *ccname;
2477  Oid constrOid;
2478 
2479  if (cdef->contype != CONSTR_CHECK)
2480  continue;
2481 
2482  if (cdef->raw_expr != NULL)
2483  {
2484  Assert(cdef->cooked_expr == NULL);
2485 
2486  /*
2487  * Transform raw parsetree to executable expression, and verify
2488  * it's valid as a CHECK constraint.
2489  */
2490  expr = cookConstraint(pstate, cdef->raw_expr,
2492  }
2493  else
2494  {
2495  Assert(cdef->cooked_expr != NULL);
2496 
2497  /*
2498  * Here, we assume the parser will only pass us valid CHECK
2499  * expressions, so we do no particular checking.
2500  */
2501  expr = stringToNode(cdef->cooked_expr);
2502  }
2503 
2504  /*
2505  * Check name uniqueness, or generate a name if none was given.
2506  */
2507  if (cdef->conname != NULL)
2508  {
2509  ListCell *cell2;
2510 
2511  ccname = cdef->conname;
2512  /* Check against other new constraints */
2513  /* Needed because we don't do CommandCounterIncrement in loop */
2514  foreach(cell2, checknames)
2515  {
2516  if (strcmp((char *) lfirst(cell2), ccname) == 0)
2517  ereport(ERROR,
2519  errmsg("check constraint \"%s\" already exists",
2520  ccname)));
2521  }
2522 
2523  /* save name for future checks */
2524  checknames = lappend(checknames, ccname);
2525 
2526  /*
2527  * Check against pre-existing constraints. If we are allowed to
2528  * merge with an existing constraint, there's no more to do here.
2529  * (We omit the duplicate constraint from the result, which is
2530  * what ATAddCheckConstraint wants.)
2531  */
2532  if (MergeWithExistingConstraint(rel, ccname, expr,
2533  allow_merge, is_local,
2534  cdef->initially_valid,
2535  cdef->is_no_inherit))
2536  continue;
2537  }
2538  else
2539  {
2540  /*
2541  * When generating a name, we want to create "tab_col_check" for a
2542  * column constraint and "tab_check" for a table constraint. We
2543  * no longer have any info about the syntactic positioning of the
2544  * constraint phrase, so we approximate this by seeing whether the
2545  * expression references more than one column. (If the user
2546  * played by the rules, the result is the same...)
2547  *
2548  * Note: pull_var_clause() doesn't descend into sublinks, but we
2549  * eliminated those above; and anyway this only needs to be an
2550  * approximate answer.
2551  */
2552  List *vars;
2553  char *colname;
2554 
2555  vars = pull_var_clause(expr, 0);
2556 
2557  /* eliminate duplicates */
2558  vars = list_union(NIL, vars);
2559 
2560  if (list_length(vars) == 1)
2561  colname = get_attname(RelationGetRelid(rel),
2562  ((Var *) linitial(vars))->varattno,
2563  true);
2564  else
2565  colname = NULL;
2566 
2568  colname,
2569  "check",
2570  RelationGetNamespace(rel),
2571  checknames);
2572 
2573  /* save name for future checks */
2574  checknames = lappend(checknames, ccname);
2575  }
2576 
2577  /*
2578  * OK, store it.
2579  */
2580  constrOid =
2581  StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
2582  is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
2583 
2584  numchecks++;
2585 
2586  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2587  cooked->contype = CONSTR_CHECK;
2588  cooked->conoid = constrOid;
2589  cooked->name = ccname;
2590  cooked->attnum = 0;
2591  cooked->expr = expr;
2592  cooked->skip_validation = cdef->skip_validation;
2593  cooked->is_local = is_local;
2594  cooked->inhcount = is_local ? 0 : 1;
2595  cooked->is_no_inherit = cdef->is_no_inherit;
2596  cookedConstraints = lappend(cookedConstraints, cooked);
2597  }
2598 
2599  /*
2600  * Update the count of constraints in the relation's pg_class tuple. We do
2601  * this even if there was no change, in order to ensure that an SI update
2602  * message is sent out for the pg_class tuple, which will force other
2603  * backends to rebuild their relcache entries for the rel. (This is
2604  * critical if we added defaults but not constraints.)
2605  */
2606  SetRelationNumChecks(rel, numchecks);
2607 
2608  return cookedConstraints;
2609 }
#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:568
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2772
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:2886
Definition: nodes.h:517
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:164
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:2815
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:2016
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:2622
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:2190
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 2815 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().

2820 {
2821  Node *expr;
2822 
2823  Assert(raw_default != NULL);
2824 
2825  /*
2826  * Transform raw parsetree to executable expression.
2827  */
2828  expr = transformExpr(pstate, raw_default, EXPR_KIND_COLUMN_DEFAULT);
2829 
2830  /*
2831  * Make sure default expr does not refer to any vars (we need this check
2832  * since the pstate includes the target table).
2833  */
2834  if (contain_var_clause(expr))
2835  ereport(ERROR,
2836  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2837  errmsg("cannot use column references in default expression")));
2838 
2839  /*
2840  * transformExpr() should have already rejected subqueries, aggregates,
2841  * window functions, and SRFs, based on the EXPR_KIND_ for a default
2842  * expression.
2843  */
2844 
2845  /*
2846  * Coerce the expression to the correct type and typmod, if given. This
2847  * should match the parser's processing of non-defaulted expressions ---
2848  * see transformAssignedExpr().
2849  */
2850  if (OidIsValid(atttypid))
2851  {
2852  Oid type_id = exprType(expr);
2853 
2854  expr = coerce_to_target_type(pstate, expr, type_id,
2855  atttypid, atttypmod,
2858  -1);
2859  if (expr == NULL)
2860  ereport(ERROR,
2861  (errcode(ERRCODE_DATATYPE_MISMATCH),
2862  errmsg("column \"%s\" is of type %s"
2863  " but default expression is of type %s",
2864  attname,
2866  format_type_be(type_id)),
2867  errhint("You will need to rewrite or cast the expression.")));
2868  }
2869 
2870  /*
2871  * Finally, take care of collations in the finished expression.
2872  */
2873  assign_expr_collations(pstate, expr);
2874 
2875  return expr;
2876 }
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:517
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:94
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:490
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:490
#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:94
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define Int16GetDatum(X)
Definition: postgres.h:434
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:490
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:3024
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:88
#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:13161
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:539
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:111
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:490
#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:110
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:561
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:2309
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:5448

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

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

1768 {
1769  Relation rel;
1770  HeapTuple tuple;
1771  Oid parentOid = InvalidOid,
1772  defaultPartOid = InvalidOid;
1773 
1774  /*
1775  * To drop a partition safely, we must grab exclusive lock on its parent,
1776  * because another backend might be about to execute a query on the parent
1777  * table. If it relies on previously cached partition descriptor, then it
1778  * could attempt to access the just-dropped relation as its partition. We
1779  * must therefore take a table lock strong enough to prevent all queries
1780  * on the table from proceeding until we commit and send out a
1781  * shared-cache-inval notice that will make them update their partition
1782  * descriptors.
1783  */
1784  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1785  if (!HeapTupleIsValid(tuple))
1786  elog(ERROR, "cache lookup failed for relation %u", relid);
1787  if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
1788  {
1789  parentOid = get_partition_parent(relid);
1791 
1792  /*
1793  * If this is not the default partition, dropping it will change the
1794  * default partition's partition constraint, so we must lock it.
1795  */
1796  defaultPartOid = get_default_partition_oid(parentOid);
1797  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1798  LockRelationOid(defaultPartOid, AccessExclusiveLock);
1799  }
1800 
1801  ReleaseSysCache(tuple);
1802 
1803  /*
1804  * Open and lock the relation.
1805  */
1806  rel = relation_open(relid, AccessExclusiveLock);
1807 
1808  /*
1809  * There can no longer be anyone *else* touching the relation, but we
1810  * might still have open queries or cursors, or pending trigger events, in
1811  * our own session.
1812  */
1813  CheckTableNotInUse(rel, "DROP TABLE");
1814 
1815  /*
1816  * This effectively deletes all rows in the table, and may be done in a
1817  * serializable transaction. In that case we must record a rw-conflict in
1818  * to this transaction from each transaction holding a predicate lock on
1819  * the table.
1820  */
1822 
1823  /*
1824  * Delete pg_foreign_table tuple first.
1825  */
1826  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1827  {
1828  Relation rel;
1829  HeapTuple tuple;
1830 
1831  rel = heap_open(ForeignTableRelationId, RowExclusiveLock);
1832 
1834  if (!HeapTupleIsValid(tuple))
1835  elog(ERROR, "cache lookup failed for foreign table %u", relid);
1836 
1837  CatalogTupleDelete(rel, &tuple->t_self);
1838 
1839  ReleaseSysCache(tuple);
1841  }
1842 
1843  /*
1844  * If a partitioned table, delete the pg_partitioned_table tuple.
1845  */
1846  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1848 
1849  /*
1850  * If the relation being dropped is the default partition itself,
1851  * invalidate its entry in pg_partitioned_table.
1852  */
1853  if (relid == defaultPartOid)
1855 
1856  /*
1857  * Schedule unlinking of the relation's physical files at commit.
1858  */
1859  if (rel->rd_rel->relkind != RELKIND_VIEW &&
1860  rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
1861  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1862  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1863  {
1864  RelationDropStorage(rel);
1865  }
1866 
1867  /*
1868  * Close relcache entry, but *keep* AccessExclusiveLock on the relation
1869  * until transaction commit. This ensures no one else will try to do
1870  * something with the doomed relation.
1871  */
1872  relation_close(rel, NoLock);
1873 
1874  /*
1875  * Remove any associated relation synchronization states.
1876  */
1878 
1879  /*
1880  * Forget any ON COMMIT action for the rel
1881  */
1882  remove_on_commit_action(relid);
1883 
1884  /*
1885  * Flush the relation from the relcache. We want to do this before
1886  * starting to remove catalog entries, just to be certain that no relcache
1887  * entry rebuild will happen partway through. (That should not really
1888  * matter, since we don't do CommandCounterIncrement here, but let's be
1889  * safe.)
1890  */
1891  RelationForgetRelation(relid);
1892 
1893  /*
1894  * remove inheritance information
1895  */
1897 
1898  /*
1899  * delete statistics
1900  */
1901  RemoveStatistics(relid, 0);
1902 
1903  /*
1904  * delete attribute tuples
1905  */
1906  DeleteAttributeTuples(relid);
1907 
1908  /*
1909  * delete relation tuple
1910  */
1911  DeleteRelationTuple(relid);
1912 
1913  if (OidIsValid(parentOid))
1914  {
1915  /*
1916  * If this is not the default partition, the partition constraint of
1917  * the default partition has changed to include the portion of the key
1918  * space previously covered by the dropped partition.
1919  */
1920  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1921  CacheInvalidateRelcacheByRelid(defaultPartOid);
1922 
1923  /*
1924  * Invalidate the parent's relcache so that the partition is no longer
1925  * included in its partition descriptor.
1926  */
1927  CacheInvalidateRelcacheByRelid(parentOid);
1928  /* keep the lock */
1929  }
1930 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
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:13192
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1270
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2525
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:490
#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:1292
bool relispartition
Definition: pg_class.h:69
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3208
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:2928
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
#define AccessExclusiveLock
Definition: lockdefs.h:45
void RemovePartitionKeyByRelId(Oid relid)
Definition: heap.c:3382
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 3016 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().

3017 {
3018  List *relations = NIL;
3019  ListCell *cell;
3020 
3021  /* Open relations for processing, and grab exclusive access on each */
3022  foreach(cell, relids)
3023  {
3024  Oid rid = lfirst_oid(cell);
3025  Relation rel;
3026 
3027  rel = heap_open(rid, AccessExclusiveLock);
3028  relations = lappend(relations, rel);
3029  }
3030 
3031  /* Don't allow truncate on tables that are referenced by foreign keys */
3032  heap_truncate_check_FKs(relations, true);
3033 
3034  /* OK to do it */
3035  foreach(cell, relations)
3036  {
3037  Relation rel = lfirst(cell);
3038 
3039  /* Truncate the relation */
3040  heap_truncate_one_rel(rel);
3041 
3042  /* Close the relation, but keep exclusive lock on it until commit */
3043  heap_close(rel, NoLock);
3044  }
3045 }
#define NIL
Definition: pg_list.h:69
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:3057
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:3094
#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 3094 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().

3095 {
3096  List *oids = NIL;
3097  List *dependents;
3098  ListCell *cell;
3099 
3100  /*
3101  * Build a list of OIDs of the interesting relations.
3102  *
3103  * If a relation has no triggers, then it can neither have FKs nor be
3104  * referenced by a FK from another table, so we can ignore it.
3105  */
3106  foreach(cell, relations)
3107  {
3108  Relation rel = lfirst(cell);
3109 
3110  if (rel->rd_rel->relhastriggers)
3111  oids = lappend_oid(oids, RelationGetRelid(rel));
3112  }
3113 
3114  /*
3115  * Fast path: if no relation has triggers, none has FKs either.
3116  */
3117  if (oids == NIL)
3118  return;
3119 
3120  /*
3121  * Otherwise, must scan pg_constraint. We make one pass with all the
3122  * relations considered; if this finds nothing, then all is well.
3123  */
3124  dependents = heap_truncate_find_FKs(oids);
3125  if (dependents == NIL)
3126  return;
3127 
3128  /*
3129  * Otherwise we repeat the scan once per relation to identify a particular
3130  * pair of relations to complain about. This is pretty slow, but
3131  * performance shouldn't matter much in a failure path. The reason for
3132  * doing things this way is to ensure that the message produced is not
3133  * dependent on chance row locations within pg_constraint.
3134  */
3135  foreach(cell, oids)
3136  {
3137  Oid relid = lfirst_oid(cell);
3138  ListCell *cell2;
3139 
3140  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
3141 
3142  foreach(cell2, dependents)
3143  {
3144  Oid relid2 = lfirst_oid(cell2);
3145 
3146  if (!list_member_oid(oids, relid2))
3147  {
3148  char *relname = get_rel_name(relid);
3149  char *relname2 = get_rel_name(relid2);
3150 
3151  if (tempTables)
3152  ereport(ERROR,
3153  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3154  errmsg("unsupported ON COMMIT and foreign key combination"),
3155  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3156  relname2, relname)));
3157  else
3158  ereport(ERROR,
3159  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3160  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3161  errdetail("Table \"%s\" references \"%s\".",
3162  relname2, relname),
3163  errhint("Truncate table \"%s\" at the same time, "
3164  "or use TRUNCATE ... CASCADE.",
3165  relname2)));
3166  }
3167  }
3168  }
3169 }
#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:3186
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

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

3187 {
3188  List *result = NIL;
3189  Relation fkeyRel;
3190  SysScanDesc fkeyScan;
3191  HeapTuple tuple;
3192 
3193  /*
3194  * Must scan pg_constraint. Right now, it is a seqscan because there is
3195  * no available index on confrelid.
3196  */
3197  fkeyRel = heap_open(ConstraintRelationId, AccessShareLock);
3198 
3199  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3200  NULL, 0, NULL);
3201 
3202  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3203  {
3205 
3206  /* Not a foreign key */
3207  if (con->contype != CONSTRAINT_FOREIGN)
3208  continue;
3209 
3210  /* Not referencing one of our list of tables */
3211  if (!list_member_oid(relationIds, con->confrelid))
3212  continue;
3213 
3214  /* Add referencer unless already in input or result list */
3215  if (!list_member_oid(relationIds, con->conrelid))
3216  result = insert_ordered_unique_oid(result, con->conrelid);
3217  }
3218 
3219  systable_endscan(fkeyScan);
3220  heap_close(fkeyRel, AccessShareLock);
3221 
3222  return result;
3223 }
#define NIL
Definition: pg_list.h:69
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#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:3236
Definition: pg_list.h:45

◆ heap_truncate_one_rel()

void heap_truncate_one_rel ( Relation  rel)

Definition at line 3057 of file heap.c.

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

Referenced by ExecuteTruncateGuts(), and heap_truncate().

3058 {
3059  Oid toastrelid;
3060 
3061  /* Truncate the actual file (and discard buffers) */
3062  RelationTruncate(rel, 0);
3063 
3064  /* If the relation has indexes, truncate the indexes too */
3066 
3067  /* If there is a toast table, truncate that too */
3068  toastrelid = rel->rd_rel->reltoastrelid;
3069  if (OidIsValid(toastrelid))
3070  {
3071  Relation toastrel = heap_open(toastrelid, AccessExclusiveLock);
3072 
3073  RelationTruncate(toastrel, 0);
3074  RelationTruncateIndexes(toastrel);
3075  /* keep the lock... */
3076  heap_close(toastrel, NoLock);
3077  }
3078 }
#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:2975
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:578
#define RelationGetDescr(relation)
Definition: rel.h:433
#define Int16GetDatum(X)
Definition: postgres.h:434
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:490
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
uintptr_t Datum
Definition: postgres.h:365
#define BoolGetDatum(X)
Definition: postgres.h:385
#define CharGetDatum(X)
Definition: postgres.h:399
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define Int32GetDatum(X)
Definition: postgres.h:462
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:578
#define MultiXactIdGetDatum(X)
Definition: postgres.h:511
#define RelationGetDescr(relation)
Definition: rel.h:433
#define Int16GetDatum(X)
Definition: postgres.h:434
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:715
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
Datum Float4GetDatum(float4 X)
Definition: fmgr.c:1888
#define TransactionIdGetDatum(X)
Definition: postgres.h:504
uintptr_t Datum
Definition: postgres.h:365
#define BoolGetDatum(X)
Definition: postgres.h:385
#define CharGetDatum(X)
Definition: postgres.h:399
static Datum values[MAXATTR]
Definition: bootstrap.c:164
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
#define Int32GetDatum(X)
Definition: postgres.h:462

◆ RelationClearMissing()

void RelationClearMissing ( Relation  rel)

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

1945 {
1946  Relation attr_rel;
1947  Oid relid = RelationGetRelid(rel);
1948  int natts = RelationGetNumberOfAttributes(rel);
1949  int attnum;
1950  Datum repl_val[Natts_pg_attribute];
1951  bool repl_null[Natts_pg_attribute];
1952  bool repl_repl[Natts_pg_attribute];
1953  Form_pg_attribute attrtuple;
1954  HeapTuple tuple,
1955  newtuple;
1956 
1957  memset(repl_val, 0, sizeof(repl_val));
1958  memset(repl_null, false, sizeof(repl_null));
1959  memset(repl_repl, false, sizeof(repl_repl));
1960 
1961  repl_val[Anum_pg_attribute_atthasmissing - 1] = BoolGetDatum(false);
1962  repl_null[Anum_pg_attribute_attmissingval - 1] = true;
1963 
1964  repl_repl[Anum_pg_attribute_atthasmissing - 1] = true;
1965  repl_repl[Anum_pg_attribute_attmissingval - 1] = true;
1966 
1967 
1968  /* Get a lock on pg_attribute */
1969  attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
1970 
1971  /* process each non-system attribute, including any dropped columns */
1972  for (attnum = 1; attnum <= natts; attnum++)
1973  {
1974  tuple = SearchSysCache2(ATTNUM,
1975  ObjectIdGetDatum(relid),
1976  Int16GetDatum(attnum));
1977  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1978  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1979  attnum, relid);
1980 
1981  attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
1982 
1983  /* ignore any where atthasmissing is not true */
1984  if (attrtuple->atthasmissing)
1985  {
1986  newtuple = heap_modify_tuple(tuple, RelationGetDescr(attr_rel),
1987  repl_val, repl_null, repl_repl);
1988 
1989  CatalogTupleUpdate(attr_rel, &newtuple->t_self, newtuple);
1990 
1991  heap_freetuple(newtuple);
1992  }
1993 
1994  ReleaseSysCache(tuple);
1995  }
1996 
1997  /*
1998  * Our update of the pg_attribute rows will force a relcache rebuild, so
1999  * there's nothing else to do here.
2000  */
2001  heap_close(attr_rel, RowExclusiveLock);
2002 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#define RelationGetDescr(relation)
Definition: rel.h:433
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:413
#define Int16GetDatum(X)
Definition: postgres.h:434
#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:490
#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:365
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:385
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 1640 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().

1642 {
1643  Relation attrdef_rel;
1644  ScanKeyData scankeys[2];
1645  SysScanDesc scan;
1646  HeapTuple tuple;
1647  bool found = false;
1648 
1649  attrdef_rel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
1650 
1651  ScanKeyInit(&scankeys[0],
1652  Anum_pg_attrdef_adrelid,
1653  BTEqualStrategyNumber, F_OIDEQ,
1654  ObjectIdGetDatum(relid));
1655  ScanKeyInit(&scankeys[1],
1656  Anum_pg_attrdef_adnum,
1657  BTEqualStrategyNumber, F_INT2EQ,
1659 
1660  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1661  NULL, 2, scankeys);
1662 
1663  /* There should be at most one matching tuple, but we loop anyway */
1664  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1665  {
1666  ObjectAddress object;
1667 
1668  object.classId = AttrDefaultRelationId;
1669  object.objectId = HeapTupleGetOid(tuple);
1670  object.objectSubId = 0;
1671 
1672  performDeletion(&object, behavior,
1673  internal ? PERFORM_DELETION_INTERNAL : 0);
1674 
1675  found = true;
1676  }
1677 
1678  systable_endscan(scan);
1679  heap_close(attrdef_rel, RowExclusiveLock);
1680 
1681  if (complain && !found)
1682  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1683  relid, attnum);
1684 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define Int16GetDatum(X)
Definition: postgres.h:434
#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:490
#define ERROR
Definition: elog.h:43
#define AttrDefaultIndexId
Definition: indexing.h:87
#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:712
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:189

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

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

1695 {
1696  Relation attrdef_rel;
1697  Relation attr_rel;
1698  Relation myrel;
1699  ScanKeyData scankeys[1];
1700  SysScanDesc scan;
1701  HeapTuple tuple;
1702  Oid myrelid;
1703  AttrNumber myattnum;
1704 
1705  /* Grab an appropriate lock on the pg_attrdef relation */
1706  attrdef_rel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
1707 
1708  /* Find the pg_attrdef tuple */
1709  ScanKeyInit(&scankeys[0],
1711  BTEqualStrategyNumber, F_OIDEQ,
1712  ObjectIdGetDatum(attrdefId));
1713 
1714  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1715  NULL, 1, scankeys);
1716 
1717  tuple = systable_getnext(scan);
1718  if (!HeapTupleIsValid(tuple))
1719  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1720 
1721  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1722  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1723 
1724  /* Get an exclusive lock on the relation owning the attribute */
1725  myrel = relation_open(myrelid, AccessExclusiveLock);
1726 
1727  /* Now we can delete the pg_attrdef row */
1728  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1729 
1730  systable_endscan(scan);
1731  heap_close(attrdef_rel, RowExclusiveLock);
1732 
1733  /* Fix the pg_attribute row */
1734  attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
1735 
1736  tuple = SearchSysCacheCopy2(ATTNUM,
1737  ObjectIdGetDatum(myrelid),
1738  Int16GetDatum(myattnum));
1739  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1740  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1741  myattnum, myrelid);
1742 
1743  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1744 
1745  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1746 
1747  /*
1748  * Our update of the pg_attribute row will force a relcache rebuild, so
1749  * there's nothing else to do here.
1750  */
1751  heap_close(attr_rel, RowExclusiveLock);
1752 
1753  /* Keep lock on attribute's rel until end of xact */
1754  relation_close(myrel, NoLock);
1755 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define Int16GetDatum(X)
Definition: postgres.h:434
#define AttrDefaultOidIndexId
Definition: indexing.h:89
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:490
#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, CatalogTupleDelete(), CatalogTupleUpdate(), elog, ERROR, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, Int16GetDatum, InvalidOid, NAMEDATALEN, namestrcpy(), NoLock, ObjectIdGetDatum, relation_close(), relation_open(), 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  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1617  }
1618 
1619  /*
1620  * Because updating the pg_attribute row will trigger a relcache flush for
1621  * the target relation, we need not do anything else to notify other
1622  * backends of the change.
1623  */
1624 
1625  heap_close(attr_rel, RowExclusiveLock);
1626 
1627  if (attnum > 0)
1628  RemoveStatistics(relid, attnum);
1629 
1630  relation_close(rel, NoLock);
1631 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#define Int16GetDatum(X)
Definition: postgres.h:434
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1270
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:490
#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
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#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:2928
#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

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

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

3383 {
3384  Relation rel;
3385  HeapTuple tuple;
3386 
3387  rel = heap_open(PartitionedRelationId, RowExclusiveLock);
3388 
3389  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3390  if (!HeapTupleIsValid(tuple))
3391  elog(ERROR, "cache lookup failed for partition key of relation %u",
3392  relid);
3393 
3394  CatalogTupleDelete(rel, &tuple->t_self);
3395 
3396  ReleaseSysCache(tuple);
3398 }
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:490
#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 2928 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().

2929 {
2930  Relation pgstatistic;
2931  SysScanDesc scan;
2932  ScanKeyData key[2];
2933  int nkeys;
2934  HeapTuple tuple;
2935 
2936  pgstatistic = heap_open(StatisticRelationId, RowExclusiveLock);
2937 
2938  ScanKeyInit(&key[0],
2939  Anum_pg_statistic_starelid,
2940  BTEqualStrategyNumber, F_OIDEQ,
2941  ObjectIdGetDatum(relid));
2942 
2943  if (attnum == 0)
2944  nkeys = 1;
2945  else
2946  {
2947  ScanKeyInit(&key[1],
2948  Anum_pg_statistic_staattnum,
2949  BTEqualStrategyNumber, F_INT2EQ,
2951  nkeys = 2;
2952  }
2953 
2954  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
2955  NULL, nkeys, key);
2956 
2957  /* we must loop even when attnum != 0, in case of inherited stats */
2958  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
2959  CatalogTupleDelete(pgstatistic, &tuple->t_self);
2960 
2961  systable_endscan(scan);
2962 
2963  heap_close(pgstatistic, RowExclusiveLock);
2964 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:502
#define Int16GetDatum(X)
Definition: postgres.h:434
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:490
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:236
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ StoreAttrDefault()

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

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

2018 {
2019  char *adbin;
2020  char *adsrc;
2021  Relation adrel;
2022  HeapTuple tuple;
2023  Datum values[4];
2024  static bool nulls[4] = {false, false, false, false};
2025  Relation attrrel;
2026  HeapTuple atttup;
2027  Form_pg_attribute attStruct;
2028  Oid attrdefOid;
2029  ObjectAddress colobject,
2030  defobject;
2031 
2032  /*
2033  * Flatten expression to string form for storage.
2034  */
2035  adbin = nodeToString(expr);
2036 
2037  /*
2038  * Also deparse it to form the mostly-obsolete adsrc field.
2039  */
2040  adsrc = deparse_expression(expr,
2042  RelationGetRelid(rel)),
2043  false, false);
2044 
2045  /*
2046  * Make the pg_attrdef entry.
2047  */
2048  values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
2049  values[Anum_pg_attrdef_adnum - 1] = attnum;
2050  values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
2051  values[Anum_pg_attrdef_adsrc - 1] = CStringGetTextDatum(adsrc);
2052 
2053  adrel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
2054 
2055  tuple = heap_form_tuple(adrel->rd_att, values, nulls);
2056  attrdefOid = CatalogTupleInsert(adrel, tuple);
2057 
2058  defobject.classId = AttrDefaultRelationId;
2059  defobject.objectId = attrdefOid;
2060  defobject.objectSubId = 0;
2061 
2062  heap_close(adrel, RowExclusiveLock);
2063 
2064  /* now can free some of the stuff allocated above */
2065  pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
2066  pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
2067  heap_freetuple(tuple);
2068  pfree(adbin);
2069  pfree(adsrc);
2070 
2071  /*
2072  * Update the pg_attribute entry for the column to show that a default
2073  * exists.
2074  */
2075  attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
2076  atttup = SearchSysCacheCopy2(ATTNUM,
2079  if (!HeapTupleIsValid(atttup))
2080  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2081  attnum, RelationGetRelid(rel));
2082  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2083  if (!attStruct->atthasdef)
2084  {
2085  Form_pg_attribute defAttStruct;
2086 
2087  ExprState *exprState;
2088  Expr *expr2 = (Expr *) expr;
2089  EState *estate = NULL;
2090  ExprContext *econtext;
2091  Datum valuesAtt[Natts_pg_attribute];
2092  bool nullsAtt[Natts_pg_attribute];
2093  bool replacesAtt[Natts_pg_attribute];
2094  Datum missingval = (Datum) 0;
2095  bool missingIsNull = true;
2096 
2097  MemSet(valuesAtt, 0, sizeof(valuesAtt));
2098  MemSet(nullsAtt, false, sizeof(nullsAtt));
2099  MemSet(replacesAtt, false, sizeof(replacesAtt));
2100  valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2101  replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2102 
2103  if (add_column_mode)
2104  {
2105  expr2 = expression_planner(expr2);
2106  estate = CreateExecutorState();
2107  exprState = ExecPrepareExpr(expr2, estate);
2108  econtext = GetPerTupleExprContext(estate);
2109 
2110  missingval = ExecEvalExpr(exprState, econtext,
2111  &missingIsNull);
2112 
2113  FreeExecutorState(estate);
2114 
2115  defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1);
2116 
2117  if (missingIsNull)
2118  {
2119  /* if the default evaluates to NULL, just store a NULL array */
2120  missingval = (Datum) 0;
2121  }
2122  else
2123  {
2124  /* otherwise make a one-element array of the value */
2125  missingval = PointerGetDatum(
2126  construct_array(&missingval,
2127  1,
2128  defAttStruct->atttypid,
2129  defAttStruct->attlen,
2130  defAttStruct->attbyval,
2131  defAttStruct->attalign));
2132  }
2133 
2134  valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
2135  replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2136  valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2137  replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2138  nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull;
2139  }
2140  atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2141  valuesAtt, nullsAtt, replacesAtt);
2142 
2143  CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
2144 
2145  if (!missingIsNull)
2146  pfree(DatumGetPointer(missingval));
2147 
2148  }
2149  heap_close(attrrel, RowExclusiveLock);
2150  heap_freetuple(atttup);
2151 
2152  /*
2153  * Make a dependency so that the pg_attrdef entry goes away if the column
2154  * (or whole table) is deleted.
2155  */
2156  colobject.classId = RelationRelationId;
2157  colobject.objectId = RelationGetRelid(rel);
2158  colobject.objectSubId = attnum;
2159 
2160  recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
2161 
2162  /*
2163  * Record dependencies on objects used in the expression, too.
2164  */
2165  recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
2166 
2167  /*
2168  * Post creation hook for attribute defaults.
2169  *
2170  * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
2171  * couple of deletion/creation of the attribute's default entry, so the
2172  * callee should check existence of an older version of this entry if it
2173  * needs to distinguish.
2174  */
2175  InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
2176  RelationGetRelid(rel), attnum, is_internal);
2177 
2178  return attrdefOid;
2179 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#define RelationGetDescr(relation)
Definition: rel.h:433
#define PointerGetDatum(X)
Definition: postgres.h:539
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
Expr * expression_planner(Expr *expr)
Definition: planner.c:5883
#define Int16GetDatum(X)
Definition: postgres.h:434
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:489
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#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:281
#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:365
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:532
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define CStringGetTextDatum(s)
Definition: builtins.h:95
char * nodeToString(const void *obj)
Definition: outfuncs.c:4331
#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 3413 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().

3414 {
3415  Relation classRel;
3416  HeapTuple tuple,
3417  newtuple;
3418  Datum new_val[Natts_pg_class];
3419  bool new_null[Natts_pg_class],
3420  new_repl[Natts_pg_class];
3421  Oid defaultPartOid;
3422 
3423  /* Update pg_class tuple */
3424  classRel = heap_open(RelationRelationId, RowExclusiveLock);
3425  tuple = SearchSysCacheCopy1(RELOID,
3427  if (!HeapTupleIsValid(tuple))
3428  elog(ERROR, "cache lookup failed for relation %u",
3429  RelationGetRelid(rel));
3430 
3431 #ifdef USE_ASSERT_CHECKING
3432  {
3433  Form_pg_class classForm;
3434  bool isnull;
3435 
3436  classForm = (Form_pg_class) GETSTRUCT(tuple);
3437  Assert(!classForm->relispartition);
3438  (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
3439  &isnull);
3440  Assert(isnull);
3441  }
3442 #endif
3443 
3444  /* Fill in relpartbound value */
3445  memset(new_val, 0, sizeof(new_val));
3446  memset(new_null, false, sizeof(new_null));
3447  memset(new_repl, false, sizeof(new_repl));
3448  new_val[Anum_pg_class_relpartbound - 1] = CStringGetTextDatum(nodeToString(bound));
3449  new_null[Anum_pg_class_relpartbound - 1] = false;
3450  new_repl[Anum_pg_class_relpartbound - 1] = true;
3451  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3452  new_val, new_null, new_repl);
3453  /* Also set the flag */
3454  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3455  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3456  heap_freetuple(newtuple);
3457  heap_close(classRel, RowExclusiveLock);
3458 
3459  /*
3460  * If we're storing bounds for the default partition, update
3461  * pg_partitioned_table too.
3462  */
3463  if (bound->is_default)
3465  RelationGetRelid(rel));
3466 
3467  /* Make these updates visible */
3469 
3470  /*
3471  * The partition constraint for the default partition depends on the
3472  * partition bounds of every other partition, so we must invalidate the
3473  * relcache entry for that partition every time a partition is added or
3474  * removed.
3475  */
3476  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3477  if (OidIsValid(defaultPartOid))
3478  CacheInvalidateRelcacheByRelid(defaultPartOid);
3479 
3480  CacheInvalidateRelcache(parent);
3481 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#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:490
#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:1292
bool relispartition
Definition: pg_class.h:69
uintptr_t Datum
Definition: postgres.h:365
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:1233
FormData_pg_class * Form_pg_class
Definition: pg_class.h:92
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define CStringGetTextDatum(s)
Definition: builtins.h:95
char * nodeToString(const void *obj)
Definition: outfuncs.c:4331
#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 3270 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().

3277 {
3278  int i;
3279  int2vector *partattrs_vec;
3280  oidvector *partopclass_vec;
3281  oidvector *partcollation_vec;
3282  Datum partexprDatum;
3283  Relation pg_partitioned_table;
3284  HeapTuple tuple;
3285  Datum values[Natts_pg_partitioned_table];
3286  bool nulls[Natts_pg_partitioned_table];
3287  ObjectAddress myself;
3288  ObjectAddress referenced;
3289 
3290  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3291 
3292  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3293  partattrs_vec = buildint2vector(partattrs, partnatts);
3294  partopclass_vec = buildoidvector(partopclass, partnatts);
3295  partcollation_vec = buildoidvector(partcollation, partnatts);
3296 
3297  /* Convert the expressions (if any) to a text datum */
3298  if (partexprs)
3299  {
3300  char *exprString;
3301 
3302  exprString = nodeToString(partexprs);
3303  partexprDatum = CStringGetTextDatum(exprString);
3304  pfree(exprString);
3305  }
3306  else
3307  partexprDatum = (Datum) 0;
3308 
3309  pg_partitioned_table = heap_open(PartitionedRelationId, RowExclusiveLock);
3310 
3311  MemSet(nulls, false, sizeof(nulls));
3312 
3313  /* Only this can ever be NULL */
3314  if (!partexprDatum)
3315  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3316 
3317  values[Anum_pg_partitioned_table_partrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
3318  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3319  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3320  values[Anum_pg_partitioned_table_partdefid - 1] = ObjectIdGetDatum(InvalidOid);
3321  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3322  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3323  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3324  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3325 
3326  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3327 
3328  CatalogTupleInsert(pg_partitioned_table, tuple);
3329  heap_close(pg_partitioned_table, RowExclusiveLock);
3330 
3331  /* Mark this relation as dependent on a few things as follows */
3332  myself.classId = RelationRelationId;
3333  myself.objectId = RelationGetRelid(rel);;
3334  myself.objectSubId = 0;
3335 
3336  /* Operator class and collation per key column */
3337  for (i = 0; i < partnatts; i++)
3338  {
3339  referenced.classId = OperatorClassRelationId;
3340  referenced.objectId = partopclass[i];
3341  referenced.objectSubId = 0;
3342 
3343  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3344 
3345  /* The default collation is pinned, so don't bother recording it */
3346  if (OidIsValid(partcollation[i]) &&
3347  partcollation[i] != DEFAULT_COLLATION_OID)
3348  {
3349  referenced.classId = CollationRelationId;
3350  referenced.objectId = partcollation[i];
3351  referenced.objectSubId = 0;
3352  }
3353 
3354  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3355  }
3356 
3357  /*
3358  * Anything mentioned in the expressions. We must ignore the column
3359  * references, which will depend on the table itself; there is no separate
3360  * partition key object.
3361  */
3362  if (partexprs)
3364  (Node *) partexprs,
3365  RelationGetRelid(rel),
3367  DEPENDENCY_AUTO, true);
3368 
3369  /*
3370  * We must invalidate the relcache so that the next
3371  * CommandCounterIncrement() will cause the same to be rebuilt using the
3372  * information in just created catalog entry.
3373  */
3375 }
Definition: c.h:555
#define RelationGetDescr(relation)
Definition: rel.h:433
#define PointerGetDatum(X)
Definition: postgres.h:539
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:110
#define Int16GetDatum(X)
Definition: postgres.h:434
Definition: nodes.h:517
#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:490
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:365
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:399
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
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:4331
#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