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, 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)
 
Oid StoreAttrDefault (Relation rel, AttrNumber attnum, Node *expr, bool is_internal)
 
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 2230 of file heap.c.

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

2236 {
2237  List *cookedConstraints = NIL;
2239  TupleConstr *oldconstr;
2240  int numoldchecks;
2241  ParseState *pstate;
2242  RangeTblEntry *rte;
2243  int numchecks;
2244  List *checknames;
2245  ListCell *cell;
2246  Node *expr;
2247  CookedConstraint *cooked;
2248 
2249  /*
2250  * Get info about existing constraints.
2251  */
2252  tupleDesc = RelationGetDescr(rel);
2253  oldconstr = tupleDesc->constr;
2254  if (oldconstr)
2255  numoldchecks = oldconstr->num_check;
2256  else
2257  numoldchecks = 0;
2258 
2259  /*
2260  * Create a dummy ParseState and insert the target relation as its sole
2261  * rangetable entry. We need a ParseState for transformExpr.
2262  */
2263  pstate = make_parsestate(NULL);
2264  rte = addRangeTableEntryForRelation(pstate,
2265  rel,
2266  NULL,
2267  false,
2268  true);
2269  addRTEtoQuery(pstate, rte, true, true, true);
2270 
2271  /*
2272  * Process column default expressions.
2273  */
2274  foreach(cell, newColDefaults)
2275  {
2276  RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
2277  Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
2278  Oid defOid;
2279 
2280  expr = cookDefault(pstate, colDef->raw_default,
2281  atp->atttypid, atp->atttypmod,
2282  NameStr(atp->attname));
2283 
2284  /*
2285  * If the expression is just a NULL constant, we do not bother to make
2286  * an explicit pg_attrdef entry, since the default behavior is
2287  * equivalent.
2288  *
2289  * Note a nonobvious property of this test: if the column is of a
2290  * domain type, what we'll get is not a bare null Const but a
2291  * CoerceToDomain expr, so we will not discard the default. This is
2292  * critical because the column default needs to be retained to
2293  * override any default that the domain might have.
2294  */
2295  if (expr == NULL ||
2296  (IsA(expr, Const) &&((Const *) expr)->constisnull))
2297  continue;
2298 
2299  defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
2300 
2301  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2302  cooked->contype = CONSTR_DEFAULT;
2303  cooked->conoid = defOid;
2304  cooked->name = NULL;
2305  cooked->attnum = colDef->attnum;
2306  cooked->expr = expr;
2307  cooked->skip_validation = false;
2308  cooked->is_local = is_local;
2309  cooked->inhcount = is_local ? 0 : 1;
2310  cooked->is_no_inherit = false;
2311  cookedConstraints = lappend(cookedConstraints, cooked);
2312  }
2313 
2314  /*
2315  * Process constraint expressions.
2316  */
2317  numchecks = numoldchecks;
2318  checknames = NIL;
2319  foreach(cell, newConstraints)
2320  {
2321  Constraint *cdef = (Constraint *) lfirst(cell);
2322  char *ccname;
2323  Oid constrOid;
2324 
2325  if (cdef->contype != CONSTR_CHECK)
2326  continue;
2327 
2328  if (cdef->raw_expr != NULL)
2329  {
2330  Assert(cdef->cooked_expr == NULL);
2331 
2332  /*
2333  * Transform raw parsetree to executable expression, and verify
2334  * it's valid as a CHECK constraint.
2335  */
2336  expr = cookConstraint(pstate, cdef->raw_expr,
2338  }
2339  else
2340  {
2341  Assert(cdef->cooked_expr != NULL);
2342 
2343  /*
2344  * Here, we assume the parser will only pass us valid CHECK
2345  * expressions, so we do no particular checking.
2346  */
2347  expr = stringToNode(cdef->cooked_expr);
2348  }
2349 
2350  /*
2351  * Check name uniqueness, or generate a name if none was given.
2352  */
2353  if (cdef->conname != NULL)
2354  {
2355  ListCell *cell2;
2356 
2357  ccname = cdef->conname;
2358  /* Check against other new constraints */
2359  /* Needed because we don't do CommandCounterIncrement in loop */
2360  foreach(cell2, checknames)
2361  {
2362  if (strcmp((char *) lfirst(cell2), ccname) == 0)
2363  ereport(ERROR,
2365  errmsg("check constraint \"%s\" already exists",
2366  ccname)));
2367  }
2368 
2369  /* save name for future checks */
2370  checknames = lappend(checknames, ccname);
2371 
2372  /*
2373  * Check against pre-existing constraints. If we are allowed to
2374  * merge with an existing constraint, there's no more to do here.
2375  * (We omit the duplicate constraint from the result, which is
2376  * what ATAddCheckConstraint wants.)
2377  */
2378  if (MergeWithExistingConstraint(rel, ccname, expr,
2379  allow_merge, is_local,
2380  cdef->initially_valid,
2381  cdef->is_no_inherit))
2382  continue;
2383  }
2384  else
2385  {
2386  /*
2387  * When generating a name, we want to create "tab_col_check" for a
2388  * column constraint and "tab_check" for a table constraint. We
2389  * no longer have any info about the syntactic positioning of the
2390  * constraint phrase, so we approximate this by seeing whether the
2391  * expression references more than one column. (If the user
2392  * played by the rules, the result is the same...)
2393  *
2394  * Note: pull_var_clause() doesn't descend into sublinks, but we
2395  * eliminated those above; and anyway this only needs to be an
2396  * approximate answer.
2397  */
2398  List *vars;
2399  char *colname;
2400 
2401  vars = pull_var_clause(expr, 0);
2402 
2403  /* eliminate duplicates */
2404  vars = list_union(NIL, vars);
2405 
2406  if (list_length(vars) == 1)
2407  colname = get_attname(RelationGetRelid(rel),
2408  ((Var *) linitial(vars))->varattno,
2409  true);
2410  else
2411  colname = NULL;
2412 
2414  colname,
2415  "check",
2416  RelationGetNamespace(rel),
2417  checknames);
2418 
2419  /* save name for future checks */
2420  checknames = lappend(checknames, ccname);
2421  }
2422 
2423  /*
2424  * OK, store it.
2425  */
2426  constrOid =
2427  StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
2428  is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
2429 
2430  numchecks++;
2431 
2432  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2433  cooked->contype = CONSTR_CHECK;
2434  cooked->conoid = constrOid;
2435  cooked->name = ccname;
2436  cooked->attnum = 0;
2437  cooked->expr = expr;
2438  cooked->skip_validation = cdef->skip_validation;
2439  cooked->is_local = is_local;
2440  cooked->inhcount = is_local ? 0 : 1;
2441  cooked->is_no_inherit = cdef->is_no_inherit;
2442  cookedConstraints = lappend(cookedConstraints, cooked);
2443  }
2444 
2445  /*
2446  * Update the count of constraints in the relation's pg_class tuple. We do
2447  * this even if there was no change, in order to ensure that an SI update
2448  * message is sent out for the pg_class tuple, which will force other
2449  * backends to rebuild their relcache entries for the rel. (This is
2450  * critical if we added defaults but not constraints.)
2451  */
2452  SetRelationNumChecks(rel, numchecks);
2453 
2454  return cookedConstraints;
2455 }
#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:38
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2618
bool is_no_inherit
Definition: heap.h:38
AttrNumber attnum
Definition: heap.h:24
#define RelationGetDescr(relation)
Definition: rel.h:437
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
Node * raw_expr
Definition: parsenodes.h:2099
static Node * cookConstraint(ParseState *pstate, Node *raw_constraint, char *relname)
Definition: heap.c:2732
Definition: nodes.h:513
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:2092
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:163
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname)
Definition: heap.c:2661
AttrNumber attnum
Definition: heap.h:33
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
int inhcount
Definition: heap.h:37
#define RelationGetRelationName(relation)
Definition: rel.h:445
Node * raw_default
Definition: heap.h:25
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
bool skip_validation
Definition: heap.h:35
ConstrType contype
Definition: heap.h:30
#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
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:2468
TupleDesc rd_att
Definition: rel.h:115
bool is_no_inherit
Definition: parsenodes.h:2098
bool initially_valid
Definition: parsenodes.h:2130
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
TupleConstr * constr
Definition: tupdesc.h:84
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:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid conoid
Definition: heap.h:31
#define NameStr(name)
Definition: c.h:565
ConstrType contype
Definition: parsenodes.h:2089
Node * expr
Definition: heap.h:34
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
uint16 num_check
Definition: tupdesc.h:42
char * cooked_expr
Definition: parsenodes.h:2100
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal)
Definition: heap.c:1930
Definition: regcomp.c:224
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
Definition: pg_list.h:45
bool skip_validation
Definition: parsenodes.h:2129
char * name
Definition: heap.h:32
#define RelationGetRelid(relation)
Definition: rel.h:425
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:2043
bool is_local
Definition: heap.h:36
#define RelationGetNamespace(relation)
Definition: rel.h:452

◆ CheckAttributeNamesTypes()

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

Definition at line 411 of file heap.c.

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

Referenced by addRangeTableEntryForFunction(), and heap_create_with_catalog().

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

◆ CheckAttributeType()

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

Definition at line 491 of file heap.c.

References AccessShareLock, ANYARRAYOID, 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, type_is_collatable(), TYPTYPE_COMPOSITE, TYPTYPE_DOMAIN, and TYPTYPE_PSEUDO.

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

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

2666 {
2667  Node *expr;
2668 
2669  Assert(raw_default != NULL);
2670 
2671  /*
2672  * Transform raw parsetree to executable expression.
2673  */
2674  expr = transformExpr(pstate, raw_default, EXPR_KIND_COLUMN_DEFAULT);
2675 
2676  /*
2677  * Make sure default expr does not refer to any vars (we need this check
2678  * since the pstate includes the target table).
2679  */
2680  if (contain_var_clause(expr))
2681  ereport(ERROR,
2682  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2683  errmsg("cannot use column references in default expression")));
2684 
2685  /*
2686  * transformExpr() should have already rejected subqueries, aggregates,
2687  * window functions, and SRFs, based on the EXPR_KIND_ for a default
2688  * expression.
2689  */
2690 
2691  /*
2692  * Coerce the expression to the correct type and typmod, if given. This
2693  * should match the parser's processing of non-defaulted expressions ---
2694  * see transformAssignedExpr().
2695  */
2696  if (OidIsValid(atttypid))
2697  {
2698  Oid type_id = exprType(expr);
2699 
2700  expr = coerce_to_target_type(pstate, expr, type_id,
2701  atttypid, atttypmod,
2704  -1);
2705  if (expr == NULL)
2706  ereport(ERROR,
2707  (errcode(ERRCODE_DATATYPE_MISMATCH),
2708  errmsg("column \"%s\" is of type %s"
2709  " but default expression is of type %s",
2710  attname,
2711  format_type_be(atttypid),
2712  format_type_be(type_id)),
2713  errhint("You will need to rewrite or cast the expression.")));
2714  }
2715 
2716  /*
2717  * Finally, take care of collations in the finished expression.
2718  */
2719  assign_expr_collations(pstate, expr);
2720 
2721  return expr;
2722 }
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:513
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:320
bool contain_var_clause(Node *node)
Definition: var.c:331
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
void assign_expr_collations(ParseState *pstate, Node *expr)
#define ERROR
Definition: elog.h:43
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
#define ereport(elevel, rest)
Definition: elog.h:122
#define Assert(condition)
Definition: c.h:688
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 1466 of file heap.c.

References Anum_pg_attribute_attrelid, AttributeRelationId, 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().

1467 {
1468  Relation attrel;
1469  SysScanDesc scan;
1470  ScanKeyData key[1];
1471  HeapTuple atttup;
1472 
1473  /* Grab an appropriate lock on the pg_attribute relation */
1475 
1476  /* Use the index to scan only attributes of the target relation */
1477  ScanKeyInit(&key[0],
1479  BTEqualStrategyNumber, F_OIDEQ,
1480  ObjectIdGetDatum(relid));
1481 
1482  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1483  NULL, 1, key);
1484 
1485  /* Delete all the matching tuples */
1486  while ((atttup = systable_getnext(scan)) != NULL)
1487  CatalogTupleDelete(attrel, &atttup->t_self);
1488 
1489  /* Clean up after the scan */
1490  systable_endscan(scan);
1491  heap_close(attrel, RowExclusiveLock);
1492 }
#define AttributeRelidNumIndexId
Definition: indexing.h:94
#define Anum_pg_attribute_attrelid
Definition: pg_attribute.h:195
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define AttributeRelationId
Definition: pg_attribute.h:33
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#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:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#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:1290
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 1437 of file heap.c.

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

Referenced by heap_drop_with_catalog(), and index_drop().

1438 {
1439  Relation pg_class_desc;
1440  HeapTuple tup;
1441 
1442  /* Grab an appropriate lock on the pg_class relation */
1443  pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);
1444 
1445  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1446  if (!HeapTupleIsValid(tup))
1447  elog(ERROR, "cache lookup failed for relation %u", relid);
1448 
1449  /* delete the relation tuple from pg_class, and finish up */
1450  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1451 
1452  ReleaseSysCache(tup);
1453 
1454  heap_close(pg_class_desc, RowExclusiveLock);
1455 }
#define RelationRelationId
Definition: pg_class.h:29
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#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:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219

◆ DeleteSystemAttributeTuples()

void DeleteSystemAttributeTuples ( Oid  relid)

Definition at line 1503 of file heap.c.

References Anum_pg_attribute_attnum, Anum_pg_attribute_attrelid, AttributeRelationId, 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().

1504 {
1505  Relation attrel;
1506  SysScanDesc scan;
1507  ScanKeyData key[2];
1508  HeapTuple atttup;
1509 
1510  /* Grab an appropriate lock on the pg_attribute relation */
1512 
1513  /* Use the index to scan only system attributes of the target relation */
1514  ScanKeyInit(&key[0],
1516  BTEqualStrategyNumber, F_OIDEQ,
1517  ObjectIdGetDatum(relid));
1518  ScanKeyInit(&key[1],
1520  BTLessEqualStrategyNumber, F_INT2LE,
1521  Int16GetDatum(0));
1522 
1523  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1524  NULL, 2, key);
1525 
1526  /* Delete all the matching tuples */
1527  while ((atttup = systable_getnext(scan)) != NULL)
1528  CatalogTupleDelete(attrel, &atttup->t_self);
1529 
1530  /* Clean up after the scan */
1531  systable_endscan(scan);
1532  heap_close(attrel, RowExclusiveLock);
1533 }
#define AttributeRelidNumIndexId
Definition: indexing.h:94
#define Anum_pg_attribute_attrelid
Definition: pg_attribute.h:195
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define Anum_pg_attribute_attnum
Definition: pg_attribute.h:200
#define Int16GetDatum(X)
Definition: postgres.h:434
#define AttributeRelationId
Definition: pg_attribute.h:33
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#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:328
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#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:1290
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 250 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(), RelationOpenSmgr, RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_INDEX, RELKIND_PARTITIONED_INDEX, RELKIND_PARTITIONED_TABLE, RELKIND_SEQUENCE, and RELKIND_VIEW.

Referenced by heap_create_with_catalog(), and index_create().

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

◆ heap_create_init_fork()

void heap_create_init_fork ( Relation  rel)

Definition at line 1383 of file heap.c.

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

Referenced by ExecuteTruncate(), and heap_create_with_catalog().

1384 {
1385  Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
1386  rel->rd_rel->relkind == RELKIND_MATVIEW ||
1387  rel->rd_rel->relkind == RELKIND_TOASTVALUE);
1388  RelationOpenSmgr(rel);
1389  smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
1392 }
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:376
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
#define RELKIND_MATVIEW
Definition: pg_class.h:165
Form_pg_class rd_rel
Definition: rel.h:114
#define RelationOpenSmgr(relation)
Definition: rel.h:469
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:688
void log_smgrcreate(RelFileNode *rnode, ForkNumber forkNum)
Definition: storage.c:125
#define RELKIND_RELATION
Definition: pg_class.h:160
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,
ObjectAddress typaddress 
)

Definition at line 1022 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, GLOBALTABLESPACE_OID, heap_close, heap_create(), heap_create_init_fork(), heap_open(), InvalidOid, InvokeObjectPostCreateHookArg, IsBinaryUpgrade, IsBootstrapProcessingMode, IsNormalProcessingMode, IsUnderPostmaster, makeArrayTypeName(), moveArrayTypeName(), NamespaceRelationId, NoLock, OBJECT_SEQUENCE, OBJECT_TABLE, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, ONCOMMIT_NOOP, pfree(), PointerGetDatum, RelationData::rd_att, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnOwner(), register_on_commit_action(), RelationGetRelid, RelationRelationId, RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_TOASTVALUE, RELKIND_VIEW, RELPERSISTENCE_UNLOGGED, RowExclusiveLock, StoreConstraints(), TYPCATEGORY_ARRAY, TypeCreate(), TYPENAMENSP, TypeRelationId, TYPTYPE_BASE, and updateAclDependencies().

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

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

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

Definition at line 1759 of file heap.c.

References AccessExclusiveLock, CacheInvalidateRelcacheByRelid(), CatalogTupleDelete(), CheckTableForSerializableConflictIn(), CheckTableNotInUse(), DeleteAttributeTuples(), DeleteRelationTuple(), elog, ERROR, FOREIGNTABLEREL, ForeignTableRelationId, 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(), RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_PARTITIONED_TABLE, RELKIND_VIEW, RELOID, remove_on_commit_action(), RemovePartitionKeyByRelId(), RemoveStatistics(), RemoveSubscriptionRel(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, and update_default_partition_oid().

Referenced by doDeletion().

1760 {
1761  Relation rel;
1762  HeapTuple tuple;
1763  Oid parentOid = InvalidOid,
1764  defaultPartOid = InvalidOid;
1765 
1766  /*
1767  * To drop a partition safely, we must grab exclusive lock on its parent,
1768  * because another backend might be about to execute a query on the parent
1769  * table. If it relies on previously cached partition descriptor, then it
1770  * could attempt to access the just-dropped relation as its partition. We
1771  * must therefore take a table lock strong enough to prevent all queries
1772  * on the table from proceeding until we commit and send out a
1773  * shared-cache-inval notice that will make them update their index lists.
1774  */
1775  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1776  if (!HeapTupleIsValid(tuple))
1777  elog(ERROR, "cache lookup failed for relation %u", relid);
1778  if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
1779  {
1780  parentOid = get_partition_parent(relid);
1782 
1783  /*
1784  * If this is not the default partition, dropping it will change the
1785  * default partition's partition constraint, so we must lock it.
1786  */
1787  defaultPartOid = get_default_partition_oid(parentOid);
1788  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1789  LockRelationOid(defaultPartOid, AccessExclusiveLock);
1790  }
1791 
1792  ReleaseSysCache(tuple);
1793 
1794  /*
1795  * Open and lock the relation.
1796  */
1797  rel = relation_open(relid, AccessExclusiveLock);
1798 
1799  /*
1800  * There can no longer be anyone *else* touching the relation, but we
1801  * might still have open queries or cursors, or pending trigger events, in
1802  * our own session.
1803  */
1804  CheckTableNotInUse(rel, "DROP TABLE");
1805 
1806  /*
1807  * This effectively deletes all rows in the table, and may be done in a
1808  * serializable transaction. In that case we must record a rw-conflict in
1809  * to this transaction from each transaction holding a predicate lock on
1810  * the table.
1811  */
1813 
1814  /*
1815  * Delete pg_foreign_table tuple first.
1816  */
1817  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1818  {
1819  Relation rel;
1820  HeapTuple tuple;
1821 
1823 
1825  if (!HeapTupleIsValid(tuple))
1826  elog(ERROR, "cache lookup failed for foreign table %u", relid);
1827 
1828  CatalogTupleDelete(rel, &tuple->t_self);
1829 
1830  ReleaseSysCache(tuple);
1832  }
1833 
1834  /*
1835  * If a partitioned table, delete the pg_partitioned_table tuple.
1836  */
1837  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1839 
1840  /*
1841  * If the relation being dropped is the default partition itself,
1842  * invalidate its entry in pg_partitioned_table.
1843  */
1844  if (relid == defaultPartOid)
1846 
1847  /*
1848  * Schedule unlinking of the relation's physical files at commit.
1849  */
1850  if (rel->rd_rel->relkind != RELKIND_VIEW &&
1851  rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
1852  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1853  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1854  {
1855  RelationDropStorage(rel);
1856  }
1857 
1858  /*
1859  * Close relcache entry, but *keep* AccessExclusiveLock on the relation
1860  * until transaction commit. This ensures no one else will try to do
1861  * something with the doomed relation.
1862  */
1863  relation_close(rel, NoLock);
1864 
1865  /*
1866  * Remove any associated relation synchronization states.
1867  */
1869 
1870  /*
1871  * Forget any ON COMMIT action for the rel
1872  */
1873  remove_on_commit_action(relid);
1874 
1875  /*
1876  * Flush the relation from the relcache. We want to do this before
1877  * starting to remove catalog entries, just to be certain that no relcache
1878  * entry rebuild will happen partway through. (That should not really
1879  * matter, since we don't do CommandCounterIncrement here, but let's be
1880  * safe.)
1881  */
1882  RelationForgetRelation(relid);
1883 
1884  /*
1885  * remove inheritance information
1886  */
1888 
1889  /*
1890  * delete statistics
1891  */
1892  RemoveStatistics(relid, 0);
1893 
1894  /*
1895  * delete attribute tuples
1896  */
1897  DeleteAttributeTuples(relid);
1898 
1899  /*
1900  * delete relation tuple
1901  */
1902  DeleteRelationTuple(relid);
1903 
1904  if (OidIsValid(parentOid))
1905  {
1906  /*
1907  * If this is not the default partition, the partition constraint of
1908  * the default partition has changed to include the portion of the key
1909  * space previously covered by the dropped partition.
1910  */
1911  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1912  CacheInvalidateRelcacheByRelid(defaultPartOid);
1913 
1914  /*
1915  * Invalidate the parent's relcache so that the partition is no longer
1916  * included in its partition descriptor.
1917  */
1918  CacheInvalidateRelcacheByRelid(parentOid);
1919  /* keep the lock */
1920  }
1921 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
void RemoveSubscriptionRel(Oid subid, Oid relid)
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:3136
void remove_on_commit_action(Oid relid)
Definition: tablecmds.c:12988
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2660
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
Oid get_partition_parent(Oid relid)
Definition: partition.c:1382
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
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3115
Oid get_default_partition_oid(Oid parentId)
Definition: partition.c:3111
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
void RelationDropStorage(Relation rel)
Definition: storage.c:145
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
void DeleteRelationTuple(Oid relid)
Definition: heap.c:1437
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
static void RelationRemoveInheritance(Oid relid)
Definition: heap.c:1404
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4410
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1466
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:2774
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define AccessExclusiveLock
Definition: lockdefs.h:45
void RemovePartitionKeyByRelId(Oid relid)
Definition: heap.c:3228
#define RELKIND_VIEW
Definition: pg_class.h:164
#define ForeignTableRelationId
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#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 2862 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().

2863 {
2864  List *relations = NIL;
2865  ListCell *cell;
2866 
2867  /* Open relations for processing, and grab exclusive access on each */
2868  foreach(cell, relids)
2869  {
2870  Oid rid = lfirst_oid(cell);
2871  Relation rel;
2872 
2873  rel = heap_open(rid, AccessExclusiveLock);
2874  relations = lappend(relations, rel);
2875  }
2876 
2877  /* Don't allow truncate on tables that are referenced by foreign keys */
2878  heap_truncate_check_FKs(relations, true);
2879 
2880  /* OK to do it */
2881  foreach(cell, relations)
2882  {
2883  Relation rel = lfirst(cell);
2884 
2885  /* Truncate the relation */
2886  heap_truncate_one_rel(rel);
2887 
2888  /* Close the relation, but keep exclusive lock on it until commit */
2889  heap_close(rel, NoLock);
2890  }
2891 }
#define NIL
Definition: pg_list.h:69
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:2903
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:2940
#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:1290
#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 2940 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 ExecuteTruncate(), and heap_truncate().

2941 {
2942  List *oids = NIL;
2943  List *dependents;
2944  ListCell *cell;
2945 
2946  /*
2947  * Build a list of OIDs of the interesting relations.
2948  *
2949  * If a relation has no triggers, then it can neither have FKs nor be
2950  * referenced by a FK from another table, so we can ignore it.
2951  */
2952  foreach(cell, relations)
2953  {
2954  Relation rel = lfirst(cell);
2955 
2956  if (rel->rd_rel->relhastriggers)
2957  oids = lappend_oid(oids, RelationGetRelid(rel));
2958  }
2959 
2960  /*
2961  * Fast path: if no relation has triggers, none has FKs either.
2962  */
2963  if (oids == NIL)
2964  return;
2965 
2966  /*
2967  * Otherwise, must scan pg_constraint. We make one pass with all the
2968  * relations considered; if this finds nothing, then all is well.
2969  */
2970  dependents = heap_truncate_find_FKs(oids);
2971  if (dependents == NIL)
2972  return;
2973 
2974  /*
2975  * Otherwise we repeat the scan once per relation to identify a particular
2976  * pair of relations to complain about. This is pretty slow, but
2977  * performance shouldn't matter much in a failure path. The reason for
2978  * doing things this way is to ensure that the message produced is not
2979  * dependent on chance row locations within pg_constraint.
2980  */
2981  foreach(cell, oids)
2982  {
2983  Oid relid = lfirst_oid(cell);
2984  ListCell *cell2;
2985 
2986  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
2987 
2988  foreach(cell2, dependents)
2989  {
2990  Oid relid2 = lfirst_oid(cell2);
2991 
2992  if (!list_member_oid(oids, relid2))
2993  {
2994  char *relname = get_rel_name(relid);
2995  char *relname2 = get_rel_name(relid2);
2996 
2997  if (tempTables)
2998  ereport(ERROR,
2999  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3000  errmsg("unsupported ON COMMIT and foreign key combination"),
3001  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3002  relname2, relname)));
3003  else
3004  ereport(ERROR,
3005  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3006  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3007  errdetail("Table \"%s\" references \"%s\".",
3008  relname2, relname),
3009  errhint("Truncate table \"%s\" at the same time, "
3010  "or use TRUNCATE ... CASCADE.",
3011  relname2)));
3012  }
3013  }
3014  }
3015 }
#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:114
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:425
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3032
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

Definition at line 3032 of file heap.c.

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

Referenced by ExecuteTruncate(), and heap_truncate_check_FKs().

3033 {
3034  List *result = NIL;
3035  Relation fkeyRel;
3036  SysScanDesc fkeyScan;
3037  HeapTuple tuple;
3038 
3039  /*
3040  * Must scan pg_constraint. Right now, it is a seqscan because there is
3041  * no available index on confrelid.
3042  */
3044 
3045  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3046  NULL, 0, NULL);
3047 
3048  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3049  {
3051 
3052  /* Not a foreign key */
3053  if (con->contype != CONSTRAINT_FOREIGN)
3054  continue;
3055 
3056  /* Not referencing one of our list of tables */
3057  if (!list_member_oid(relationIds, con->confrelid))
3058  continue;
3059 
3060  /* Add referencer unless already in input or result list */
3061  if (!list_member_oid(relationIds, con->conrelid))
3062  result = insert_ordered_unique_oid(result, con->conrelid);
3063  }
3064 
3065  systable_endscan(fkeyScan);
3066  heap_close(fkeyRel, AccessShareLock);
3067 
3068  return result;
3069 }
#define NIL
Definition: pg_list.h:69
#define CONSTRAINT_FOREIGN
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#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:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#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:77
static List * insert_ordered_unique_oid(List *list, Oid datum)
Definition: heap.c:3082
#define ConstraintRelationId
Definition: pg_constraint.h:29
Definition: pg_list.h:45

◆ heap_truncate_one_rel()

void heap_truncate_one_rel ( Relation  rel)

Definition at line 2903 of file heap.c.

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

Referenced by ExecuteTruncate(), and heap_truncate().

2904 {
2905  Oid toastrelid;
2906 
2907  /* Truncate the actual file (and discard buffers) */
2908  RelationTruncate(rel, 0);
2909 
2910  /* If the relation has indexes, truncate the indexes too */
2912 
2913  /* If there is a toast table, truncate that too */
2914  toastrelid = rel->rd_rel->reltoastrelid;
2915  if (OidIsValid(toastrelid))
2916  {
2917  Relation toastrel = heap_open(toastrelid, AccessExclusiveLock);
2918 
2919  RelationTruncate(toastrel, 0);
2920  RelationTruncateIndexes(toastrel);
2921  /* keep the lock... */
2922  heap_close(toastrel, NoLock);
2923  }
2924 }
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
#define NoLock
Definition: lockdefs.h:34
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define AccessExclusiveLock
Definition: lockdefs.h:45
static void RelationTruncateIndexes(Relation heapRelation)
Definition: heap.c:2821
void RelationTruncate(Relation rel, BlockNumber nblocks)
Definition: storage.c:227

◆ InsertPgAttributeTuple()

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

Definition at line 601 of file heap.c.

References Anum_pg_attribute_attacl, Anum_pg_attribute_attalign, Anum_pg_attribute_attbyval, Anum_pg_attribute_attcacheoff, Anum_pg_attribute_attcollation, Anum_pg_attribute_attfdwoptions, Anum_pg_attribute_atthasdef, Anum_pg_attribute_attidentity, Anum_pg_attribute_attinhcount, Anum_pg_attribute_attisdropped, Anum_pg_attribute_attislocal, Anum_pg_attribute_attlen, Anum_pg_attribute_attname, Anum_pg_attribute_attndims, Anum_pg_attribute_attnotnull, Anum_pg_attribute_attnum, Anum_pg_attribute_attoptions, Anum_pg_attribute_attrelid, Anum_pg_attribute_attstattarget, Anum_pg_attribute_attstorage, Anum_pg_attribute_atttypid, Anum_pg_attribute_atttypmod, BoolGetDatum, CatalogTupleInsert(), CatalogTupleInsertWithInfo(), CharGetDatum, heap_form_tuple(), heap_freetuple(), Int16GetDatum, Int32GetDatum, NameGetDatum, Natts_pg_attribute, ObjectIdGetDatum, RelationGetDescr, and values.

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

604 {
606  bool nulls[Natts_pg_attribute];
607  HeapTuple tup;
608 
609  /* This is a tad tedious, but way cleaner than what we used to do... */
610  memset(values, 0, sizeof(values));
611  memset(nulls, false, sizeof(nulls));
612 
613  values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
614  values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
615  values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
616  values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
617  values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
618  values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
619  values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
620  values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(new_attribute->attcacheoff);
621  values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
622  values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
623  values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
624  values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
625  values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
626  values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
627  values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
628  values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
629  values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
630  values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
631  values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
632 
633  /* start out with empty permissions and empty options */
634  nulls[Anum_pg_attribute_attacl - 1] = true;
635  nulls[Anum_pg_attribute_attoptions - 1] = true;
636  nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
637 
638  tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
639 
640  /* finally insert the new tuple, update the indexes, and clean up */
641  if (indstate != NULL)
642  CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
643  else
644  CatalogTupleInsert(pg_attribute_rel, tup);
645 
646  heap_freetuple(tup);
647 }
#define Anum_pg_attribute_attrelid
Definition: pg_attribute.h:195
#define Anum_pg_attribute_attinhcount
Definition: pg_attribute.h:212
#define Anum_pg_attribute_atttypid
Definition: pg_attribute.h:197
#define Anum_pg_attribute_attlen
Definition: pg_attribute.h:199
#define NameGetDatum(X)
Definition: postgres.h:578
#define Anum_pg_attribute_attbyval
Definition: pg_attribute.h:204
#define Anum_pg_attribute_attnum
Definition: pg_attribute.h:200
#define RelationGetDescr(relation)
Definition: rel.h:437
#define Anum_pg_attribute_atthasdef
Definition: pg_attribute.h:208
#define Int16GetDatum(X)
Definition: postgres.h:434
#define Anum_pg_attribute_attndims
Definition: pg_attribute.h:201
#define Anum_pg_attribute_attacl
Definition: pg_attribute.h:214
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define Anum_pg_attribute_attislocal
Definition: pg_attribute.h:211
#define Anum_pg_attribute_attisdropped
Definition: pg_attribute.h:210
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Anum_pg_attribute_attstattarget
Definition: pg_attribute.h:198
#define Anum_pg_attribute_atttypmod
Definition: pg_attribute.h:203
#define Anum_pg_attribute_attcacheoff
Definition: pg_attribute.h:202
#define Anum_pg_attribute_attidentity
Definition: pg_attribute.h:209
uintptr_t Datum
Definition: postgres.h:365
#define Anum_pg_attribute_attalign
Definition: pg_attribute.h:206
#define BoolGetDatum(X)
Definition: postgres.h:385
#define Anum_pg_attribute_attnotnull
Definition: pg_attribute.h:207
#define Anum_pg_attribute_attfdwoptions
Definition: pg_attribute.h:216
#define CharGetDatum(X)
Definition: postgres.h:399
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define Int32GetDatum(X)
Definition: postgres.h:462
#define Anum_pg_attribute_attoptions
Definition: pg_attribute.h:215
#define Natts_pg_attribute
Definition: pg_attribute.h:194
#define Anum_pg_attribute_attcollation
Definition: pg_attribute.h:213
Oid CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:186
#define Anum_pg_attribute_attstorage
Definition: pg_attribute.h:205
#define Anum_pg_attribute_attname
Definition: pg_attribute.h:196

◆ InsertPgClassTuple()

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

Definition at line 767 of file heap.c.

References Anum_pg_class_relacl, Anum_pg_class_relallvisible, Anum_pg_class_relam, Anum_pg_class_relchecks, Anum_pg_class_relfilenode, Anum_pg_class_relforcerowsecurity, Anum_pg_class_relfrozenxid, Anum_pg_class_relhasindex, Anum_pg_class_relhasoids, Anum_pg_class_relhaspkey, Anum_pg_class_relhasrules, Anum_pg_class_relhassubclass, Anum_pg_class_relhastriggers, Anum_pg_class_relispartition, Anum_pg_class_relispopulated, Anum_pg_class_relisshared, Anum_pg_class_relkind, Anum_pg_class_relminmxid, Anum_pg_class_relname, Anum_pg_class_relnamespace, Anum_pg_class_relnatts, Anum_pg_class_reloftype, Anum_pg_class_reloptions, Anum_pg_class_relowner, Anum_pg_class_relpages, Anum_pg_class_relpartbound, Anum_pg_class_relpersistence, Anum_pg_class_relreplident, Anum_pg_class_relrowsecurity, Anum_pg_class_reltablespace, Anum_pg_class_reltoastrelid, Anum_pg_class_reltuples, Anum_pg_class_reltype, BoolGetDatum, CatalogTupleInsert(), CharGetDatum, Float4GetDatum(), heap_form_tuple(), heap_freetuple(), HeapTupleSetOid, Int16GetDatum, Int32GetDatum, MultiXactIdGetDatum, NameGetDatum, Natts_pg_class, ObjectIdGetDatum, RelationData::rd_rel, RelationGetDescr, TransactionIdGetDatum, and values.

Referenced by AddNewRelationTuple(), and index_create().

772 {
773  Form_pg_class rd_rel = new_rel_desc->rd_rel;
775  bool nulls[Natts_pg_class];
776  HeapTuple tup;
777 
778  /* This is a tad tedious, but way cleaner than what we used to do... */
779  memset(values, 0, sizeof(values));
780  memset(nulls, false, sizeof(nulls));
781 
782  values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
783  values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
784  values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
785  values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
786  values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
787  values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
788  values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
789  values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
790  values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
791  values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
792  values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
793  values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
794  values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
795  values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
796  values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
797  values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
798  values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
799  values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
800  values[Anum_pg_class_relhasoids - 1] = BoolGetDatum(rd_rel->relhasoids);
801  values[Anum_pg_class_relhaspkey - 1] = BoolGetDatum(rd_rel->relhaspkey);
802  values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
803  values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
804  values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
805  values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
806  values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
807  values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
808  values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
809  values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
810  values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
811  values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
812  if (relacl != (Datum) 0)
813  values[Anum_pg_class_relacl - 1] = relacl;
814  else
815  nulls[Anum_pg_class_relacl - 1] = true;
816  if (reloptions != (Datum) 0)
817  values[Anum_pg_class_reloptions - 1] = reloptions;
818  else
819  nulls[Anum_pg_class_reloptions - 1] = true;
820 
821  /* relpartbound is set by updating this tuple, if necessary */
822  nulls[Anum_pg_class_relpartbound - 1] = true;
823 
824  tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
825 
826  /*
827  * The new tuple must have the oid already chosen for the rel. Sure would
828  * be embarrassing to do this sort of thing in polite company.
829  */
830  HeapTupleSetOid(tup, new_rel_oid);
831 
832  /* finally insert the new tuple, update the indexes, and clean up */
833  CatalogTupleInsert(pg_class_desc, tup);
834 
835  heap_freetuple(tup);
836 }
#define Natts_pg_class
Definition: pg_class.h:102
#define Anum_pg_class_relhasindex
Definition: pg_class.h:115
#define Anum_pg_class_relpersistence
Definition: pg_class.h:117
#define NameGetDatum(X)
Definition: postgres.h:578
#define Anum_pg_class_relacl
Definition: pg_class.h:133
#define MultiXactIdGetDatum(X)
Definition: postgres.h:511
#define RelationGetDescr(relation)
Definition: rel.h:437
#define Anum_pg_class_relispartition
Definition: pg_class.h:130
#define Anum_pg_class_reloptions
Definition: pg_class.h:134
#define Anum_pg_class_reltablespace
Definition: pg_class.h:110
#define Int16GetDatum(X)
Definition: postgres.h:434
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
Form_pg_class rd_rel
Definition: rel.h:114
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
#define Anum_pg_class_relispopulated
Definition: pg_class.h:128
#define Anum_pg_class_relnatts
Definition: pg_class.h:119
#define Anum_pg_class_relnamespace
Definition: pg_class.h:104
#define Anum_pg_class_relfilenode
Definition: pg_class.h:109
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:703
#define Anum_pg_class_relhasrules
Definition: pg_class.h:123
#define Anum_pg_class_relkind
Definition: pg_class.h:118
#define Anum_pg_class_relhasoids
Definition: pg_class.h:121
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Anum_pg_class_reltype
Definition: pg_class.h:105
#define Anum_pg_class_reloftype
Definition: pg_class.h:106
Datum Float4GetDatum(float4 X)
Definition: fmgr.c:1798
#define Anum_pg_class_relname
Definition: pg_class.h:103
#define Anum_pg_class_relpages
Definition: pg_class.h:111
#define Anum_pg_class_relminmxid
Definition: pg_class.h:132
#define Anum_pg_class_relreplident
Definition: pg_class.h:129
#define TransactionIdGetDatum(X)
Definition: postgres.h:504
#define Anum_pg_class_relhassubclass
Definition: pg_class.h:125
#define Anum_pg_class_relisshared
Definition: pg_class.h:116
uintptr_t Datum
Definition: postgres.h:365
#define Anum_pg_class_reltuples
Definition: pg_class.h:112
#define BoolGetDatum(X)
Definition: postgres.h:385
#define Anum_pg_class_relpartbound
Definition: pg_class.h:135
#define Anum_pg_class_relhaspkey
Definition: pg_class.h:122
#define Anum_pg_class_relallvisible
Definition: pg_class.h:113
#define Anum_pg_class_reltoastrelid
Definition: pg_class.h:114
#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:95
#define Int32GetDatum(X)
Definition: postgres.h:462
#define Anum_pg_class_relforcerowsecurity
Definition: pg_class.h:127
#define Anum_pg_class_relam
Definition: pg_class.h:108
#define Anum_pg_class_relfrozenxid
Definition: pg_class.h:131
#define Anum_pg_class_relhastriggers
Definition: pg_class.h:124
#define Anum_pg_class_relchecks
Definition: pg_class.h:120
#define Anum_pg_class_relrowsecurity
Definition: pg_class.h:126
#define Anum_pg_class_relowner
Definition: pg_class.h:107

◆ RemoveAttrDefault()

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

Definition at line 1632 of file heap.c.

References Anum_pg_attrdef_adnum, Anum_pg_attrdef_adrelid, AttrDefaultIndexId, AttrDefaultRelationId, 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().

1634 {
1635  Relation attrdef_rel;
1636  ScanKeyData scankeys[2];
1637  SysScanDesc scan;
1638  HeapTuple tuple;
1639  bool found = false;
1640 
1642 
1643  ScanKeyInit(&scankeys[0],
1645  BTEqualStrategyNumber, F_OIDEQ,
1646  ObjectIdGetDatum(relid));
1647  ScanKeyInit(&scankeys[1],
1649  BTEqualStrategyNumber, F_INT2EQ,
1650  Int16GetDatum(attnum));
1651 
1652  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1653  NULL, 2, scankeys);
1654 
1655  /* There should be at most one matching tuple, but we loop anyway */
1656  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1657  {
1658  ObjectAddress object;
1659 
1660  object.classId = AttrDefaultRelationId;
1661  object.objectId = HeapTupleGetOid(tuple);
1662  object.objectSubId = 0;
1663 
1664  performDeletion(&object, behavior,
1665  internal ? PERFORM_DELETION_INTERNAL : 0);
1666 
1667  found = true;
1668  }
1669 
1670  systable_endscan(scan);
1671  heap_close(attrdef_rel, RowExclusiveLock);
1672 
1673  if (complain && !found)
1674  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1675  relid, attnum);
1676 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#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:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#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:303
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define Anum_pg_attrdef_adrelid
Definition: pg_attrdef.h:54
#define Anum_pg_attrdef_adnum
Definition: pg_attrdef.h:55
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
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:700
#define AttrDefaultRelationId
Definition: pg_attrdef.h:29
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:189

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

Definition at line 1686 of file heap.c.

References AccessExclusiveLock, ATTNUM, AttrDefaultOidIndexId, AttrDefaultRelationId, AttributeRelationId, 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().

1687 {
1688  Relation attrdef_rel;
1689  Relation attr_rel;
1690  Relation myrel;
1691  ScanKeyData scankeys[1];
1692  SysScanDesc scan;
1693  HeapTuple tuple;
1694  Oid myrelid;
1695  AttrNumber myattnum;
1696 
1697  /* Grab an appropriate lock on the pg_attrdef relation */
1699 
1700  /* Find the pg_attrdef tuple */
1701  ScanKeyInit(&scankeys[0],
1703  BTEqualStrategyNumber, F_OIDEQ,
1704  ObjectIdGetDatum(attrdefId));
1705 
1706  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1707  NULL, 1, scankeys);
1708 
1709  tuple = systable_getnext(scan);
1710  if (!HeapTupleIsValid(tuple))
1711  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1712 
1713  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1714  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1715 
1716  /* Get an exclusive lock on the relation owning the attribute */
1717  myrel = relation_open(myrelid, AccessExclusiveLock);
1718 
1719  /* Now we can delete the pg_attrdef row */
1720  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1721 
1722  systable_endscan(scan);
1723  heap_close(attrdef_rel, RowExclusiveLock);
1724 
1725  /* Fix the pg_attribute row */
1727 
1728  tuple = SearchSysCacheCopy2(ATTNUM,
1729  ObjectIdGetDatum(myrelid),
1730  Int16GetDatum(myattnum));
1731  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1732  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1733  myattnum, myrelid);
1734 
1735  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1736 
1737  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1738 
1739  /*
1740  * Our update of the pg_attribute row will force a relcache rebuild, so
1741  * there's nothing else to do here.
1742  */
1743  heap_close(attr_rel, RowExclusiveLock);
1744 
1745  /* Keep lock on attribute's rel until end of xact */
1746  relation_close(myrel, NoLock);
1747 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define Int16GetDatum(X)
Definition: postgres.h:434
#define AttrDefaultOidIndexId
Definition: indexing.h:89
#define AttributeRelationId
Definition: pg_attribute.h:33
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#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:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#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:187
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#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:1120
#define elog
Definition: elog.h:219
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:175
#define AttrDefaultRelationId
Definition: pg_attrdef.h:29
int16 AttrNumber
Definition: attnum.h:21
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ RemoveAttributeById()

void RemoveAttributeById ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 1544 of file heap.c.

References AccessExclusiveLock, ATTNUM, AttributeRelationId, 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().

1545 {
1546  Relation rel;
1547  Relation attr_rel;
1548  HeapTuple tuple;
1549  Form_pg_attribute attStruct;
1550  char newattname[NAMEDATALEN];
1551 
1552  /*
1553  * Grab an exclusive lock on the target table, which we will NOT release
1554  * until end of transaction. (In the simple case where we are directly
1555  * dropping this column, AlterTableDropColumn already did this ... but
1556  * when cascading from a drop of some other object, we may not have any
1557  * lock.)
1558  */
1559  rel = relation_open(relid, AccessExclusiveLock);
1560 
1562 
1563  tuple = SearchSysCacheCopy2(ATTNUM,
1564  ObjectIdGetDatum(relid),
1565  Int16GetDatum(attnum));
1566  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1567  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1568  attnum, relid);
1569  attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
1570 
1571  if (attnum < 0)
1572  {
1573  /* System attribute (probably OID) ... just delete the row */
1574 
1575  CatalogTupleDelete(attr_rel, &tuple->t_self);
1576  }
1577  else
1578  {
1579  /* Dropping user attributes is lots harder */
1580 
1581  /* Mark the attribute as dropped */
1582  attStruct->attisdropped = true;
1583 
1584  /*
1585  * Set the type OID to invalid. A dropped attribute's type link
1586  * cannot be relied on (once the attribute is dropped, the type might
1587  * be too). Fortunately we do not need the type row --- the only
1588  * really essential information is the type's typlen and typalign,
1589  * which are preserved in the attribute's attlen and attalign. We set
1590  * atttypid to zero here as a means of catching code that incorrectly
1591  * expects it to be valid.
1592  */
1593  attStruct->atttypid = InvalidOid;
1594 
1595  /* Remove any NOT NULL constraint the column may have */
1596  attStruct->attnotnull = false;
1597 
1598  /* We don't want to keep stats for it anymore */
1599  attStruct->attstattarget = 0;
1600 
1601  /*
1602  * Change the column name to something that isn't likely to conflict
1603  */
1604  snprintf(newattname, sizeof(newattname),
1605  "........pg.dropped.%d........", attnum);
1606  namestrcpy(&(attStruct->attname), newattname);
1607 
1608  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1609  }
1610 
1611  /*
1612  * Because updating the pg_attribute row will trigger a relcache flush for
1613  * the target relation, we need not do anything else to notify other
1614  * backends of the change.
1615  */
1616 
1617  heap_close(attr_rel, RowExclusiveLock);
1618 
1619  if (attnum > 0)
1620  RemoveStatistics(relid, attnum);
1621 
1622  relation_close(rel, NoLock);
1623 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define Int16GetDatum(X)
Definition: postgres.h:434
#define AttributeRelationId
Definition: pg_attribute.h:33
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#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:187
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:2774
#define AccessExclusiveLock
Definition: lockdefs.h:45
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
#define elog
Definition: elog.h:219
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:175

◆ RemovePartitionKeyByRelId()

void RemovePartitionKeyByRelId ( Oid  relid)

Definition at line 3228 of file heap.c.

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

Referenced by heap_drop_with_catalog().

3229 {
3230  Relation rel;
3231  HeapTuple tuple;
3232 
3234 
3235  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3236  if (!HeapTupleIsValid(tuple))
3237  elog(ERROR, "cache lookup failed for partition key of relation %u",
3238  relid);
3239 
3240  CatalogTupleDelete(rel, &tuple->t_self);
3241 
3242  ReleaseSysCache(tuple);
3244 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#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 PartitionedRelationId
#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:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219

◆ RemoveStatistics()

void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 2774 of file heap.c.

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

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

2775 {
2776  Relation pgstatistic;
2777  SysScanDesc scan;
2778  ScanKeyData key[2];
2779  int nkeys;
2780  HeapTuple tuple;
2781 
2783 
2784  ScanKeyInit(&key[0],
2786  BTEqualStrategyNumber, F_OIDEQ,
2787  ObjectIdGetDatum(relid));
2788 
2789  if (attnum == 0)
2790  nkeys = 1;
2791  else
2792  {
2793  ScanKeyInit(&key[1],
2795  BTEqualStrategyNumber, F_INT2EQ,
2796  Int16GetDatum(attnum));
2797  nkeys = 2;
2798  }
2799 
2800  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
2801  NULL, nkeys, key);
2802 
2803  /* we must loop even when attnum != 0, in case of inherited stats */
2804  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
2805  CatalogTupleDelete(pgstatistic, &tuple->t_self);
2806 
2807  systable_endscan(scan);
2808 
2809  heap_close(pgstatistic, RowExclusiveLock);
2810 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define Int16GetDatum(X)
Definition: postgres.h:434
#define Anum_pg_statistic_staattnum
Definition: pg_statistic.h:137
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#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:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define Anum_pg_statistic_starelid
Definition: pg_statistic.h:136
#define StatisticRelationId
Definition: pg_statistic.h:29
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define StatisticRelidAttnumInhIndexId
Definition: indexing.h:234
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 
)

Definition at line 1930 of file heap.c.

References Anum_pg_attrdef_adbin, Anum_pg_attrdef_adnum, Anum_pg_attrdef_adrelid, Anum_pg_attrdef_adsrc, ATTNUM, AttrDefaultRelationId, AttributeRelationId, CatalogTupleInsert(), CatalogTupleUpdate(), ObjectAddress::classId, CStringGetTextDatum, DatumGetPointer, deparse_context_for(), deparse_expression(), DEPENDENCY_AUTO, DEPENDENCY_NORMAL, elog, ERROR, GETSTRUCT, heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), HeapTupleIsValid, Int16GetDatum, InvokeObjectPostCreateHookArg, NIL, nodeToString(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, pfree(), RelationData::rd_att, recordDependencyOn(), recordDependencyOnExpr(), RelationGetRelationName, RelationGetRelid, RelationRelationId, RowExclusiveLock, SearchSysCacheCopy2, HeapTupleData::t_self, and values.

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

1932 {
1933  char *adbin;
1934  char *adsrc;
1935  Relation adrel;
1936  HeapTuple tuple;
1937  Datum values[4];
1938  static bool nulls[4] = {false, false, false, false};
1939  Relation attrrel;
1940  HeapTuple atttup;
1941  Form_pg_attribute attStruct;
1942  Oid attrdefOid;
1943  ObjectAddress colobject,
1944  defobject;
1945 
1946  /*
1947  * Flatten expression to string form for storage.
1948  */
1949  adbin = nodeToString(expr);
1950 
1951  /*
1952  * Also deparse it to form the mostly-obsolete adsrc field.
1953  */
1954  adsrc = deparse_expression(expr,
1956  RelationGetRelid(rel)),
1957  false, false);
1958 
1959  /*
1960  * Make the pg_attrdef entry.
1961  */
1962  values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
1963  values[Anum_pg_attrdef_adnum - 1] = attnum;
1964  values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
1965  values[Anum_pg_attrdef_adsrc - 1] = CStringGetTextDatum(adsrc);
1966 
1968 
1969  tuple = heap_form_tuple(adrel->rd_att, values, nulls);
1970  attrdefOid = CatalogTupleInsert(adrel, tuple);
1971 
1972  defobject.classId = AttrDefaultRelationId;
1973  defobject.objectId = attrdefOid;
1974  defobject.objectSubId = 0;
1975 
1976  heap_close(adrel, RowExclusiveLock);
1977 
1978  /* now can free some of the stuff allocated above */
1981  heap_freetuple(tuple);
1982  pfree(adbin);
1983  pfree(adsrc);
1984 
1985  /*
1986  * Update the pg_attribute entry for the column to show that a default
1987  * exists.
1988  */
1990  atttup = SearchSysCacheCopy2(ATTNUM,
1992  Int16GetDatum(attnum));
1993  if (!HeapTupleIsValid(atttup))
1994  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1995  attnum, RelationGetRelid(rel));
1996  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
1997  if (!attStruct->atthasdef)
1998  {
1999  attStruct->atthasdef = true;
2000  CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
2001  }
2002  heap_close(attrrel, RowExclusiveLock);
2003  heap_freetuple(atttup);
2004 
2005  /*
2006  * Make a dependency so that the pg_attrdef entry goes away if the column
2007  * (or whole table) is deleted.
2008  */
2009  colobject.classId = RelationRelationId;
2010  colobject.objectId = RelationGetRelid(rel);
2011  colobject.objectSubId = attnum;
2012 
2013  recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
2014 
2015  /*
2016  * Record dependencies on objects used in the expression, too.
2017  */
2018  recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
2019 
2020  /*
2021  * Post creation hook for attribute defaults.
2022  *
2023  * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
2024  * couple of deletion/creation of the attribute's default entry, so the
2025  * callee should check existence of an older version of this entry if it
2026  * needs to distinguish.
2027  */
2029  RelationGetRelid(rel), attnum, is_internal);
2030 
2031  return attrdefOid;
2032 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationRelationId
Definition: pg_class.h:29
#define Int16GetDatum(X)
Definition: postgres.h:434
#define AttributeRelationId
Definition: pg_attribute.h:33
#define Anum_pg_attrdef_adbin
Definition: pg_attrdef.h:56
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:695
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
void pfree(void *pointer)
Definition: mcxt.c:936
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
List * deparse_context_for(const char *aliasname, Oid relid)
Definition: ruleutils.c:3080
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1363
#define RelationGetRelationName(relation)
Definition: rel.h:445
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
uintptr_t Datum
Definition: postgres.h:365
#define Anum_pg_attrdef_adsrc
Definition: pg_attrdef.h:57
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:147
TupleDesc rd_att
Definition: rel.h:115
#define Anum_pg_attrdef_adrelid
Definition: pg_attrdef.h:54
#define Anum_pg_attrdef_adnum
Definition: pg_attrdef.h:55
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition: ruleutils.c:3021
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define DatumGetPointer(X)
Definition: postgres.h:532
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4281
#define elog
Definition: elog.h:219
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:175
#define AttrDefaultRelationId
Definition: pg_attrdef.h:29
#define RelationGetRelid(relation)
Definition: rel.h:425

◆ StorePartitionBound()

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

Definition at line 3256 of file heap.c.

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

Referenced by ATExecAttachPartition(), and DefineRelation().

3257 {
3258  Relation classRel;
3259  HeapTuple tuple,
3260  newtuple;
3261  Datum new_val[Natts_pg_class];
3262  bool new_null[Natts_pg_class],
3263  new_repl[Natts_pg_class];
3264  Oid defaultPartOid;
3265 
3266  /* Update pg_class tuple */
3268  tuple = SearchSysCacheCopy1(RELOID,
3270  if (!HeapTupleIsValid(tuple))
3271  elog(ERROR, "cache lookup failed for relation %u",
3272  RelationGetRelid(rel));
3273 
3274 #ifdef USE_ASSERT_CHECKING
3275  {
3276  Form_pg_class classForm;
3277  bool isnull;
3278 
3279  classForm = (Form_pg_class) GETSTRUCT(tuple);
3280  Assert(!classForm->relispartition);
3282  &isnull);
3283  Assert(isnull);
3284  }
3285 #endif
3286 
3287  /* Fill in relpartbound value */
3288  memset(new_val, 0, sizeof(new_val));
3289  memset(new_null, false, sizeof(new_null));
3290  memset(new_repl, false, sizeof(new_repl));
3292  new_null[Anum_pg_class_relpartbound - 1] = false;
3293  new_repl[Anum_pg_class_relpartbound - 1] = true;
3294  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3295  new_val, new_null, new_repl);
3296  /* Also set the flag */
3297  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3298  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3299  heap_freetuple(newtuple);
3300  heap_close(classRel, RowExclusiveLock);
3301 
3302  /*
3303  * The partition constraint for the default partition depends on the
3304  * partition bounds of every other partition, so we must invalidate the
3305  * relcache entry for that partition every time a partition is added or
3306  * removed.
3307  */
3308  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3309  if (OidIsValid(defaultPartOid))
3310  CacheInvalidateRelcacheByRelid(defaultPartOid);
3311 
3312  CacheInvalidateRelcache(parent);
3313 }
#define Natts_pg_class
Definition: pg_class.h:102
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define RelationGetDescr(relation)
Definition: rel.h:437
#define RelationRelationId
Definition: pg_class.h:29
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:594
#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
uintptr_t Datum
Definition: postgres.h:365
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define Anum_pg_class_relpartbound
Definition: pg_class.h:135
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:688
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4281
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define RelationGetRelid(relation)
Definition: rel.h:425
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
Definition: partition.c:3094
#define RelationGetPartitionDesc(relation)
Definition: rel.h:641

◆ StorePartitionKey()

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

Definition at line 3116 of file heap.c.

References Anum_pg_partitioned_table_partattrs, Anum_pg_partitioned_table_partclass, Anum_pg_partitioned_table_partcollation, Anum_pg_partitioned_table_partdefid, Anum_pg_partitioned_table_partexprs, Anum_pg_partitioned_table_partnatts, Anum_pg_partitioned_table_partrelid, Anum_pg_partitioned_table_partstrat, Assert, buildint2vector(), buildoidvector(), CacheInvalidateRelcache(), CatalogTupleInsert(), CharGetDatum, ObjectAddress::classId, CollationRelationId, CStringGetTextDatum, DEFAULT_COLLATION_OID, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, heap_close, heap_form_tuple(), heap_open(), i, Int16GetDatum, InvalidOid, MemSet, Natts_pg_partitioned_table, nodeToString(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, OperatorClassRelationId, PartitionedRelationId, pfree(), PointerGetDatum, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetDescr, RelationGetRelid, RelationRelationId, RELKIND_PARTITIONED_TABLE, RowExclusiveLock, and values.

Referenced by DefineRelation().

3123 {
3124  int i;
3125  int2vector *partattrs_vec;
3126  oidvector *partopclass_vec;
3127  oidvector *partcollation_vec;
3128  Datum partexprDatum;
3129  Relation pg_partitioned_table;
3130  HeapTuple tuple;
3132  bool nulls[Natts_pg_partitioned_table];
3133  ObjectAddress myself;
3134  ObjectAddress referenced;
3135 
3136  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3137 
3138  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3139  partattrs_vec = buildint2vector(partattrs, partnatts);
3140  partopclass_vec = buildoidvector(partopclass, partnatts);
3141  partcollation_vec = buildoidvector(partcollation, partnatts);
3142 
3143  /* Convert the expressions (if any) to a text datum */
3144  if (partexprs)
3145  {
3146  char *exprString;
3147 
3148  exprString = nodeToString(partexprs);
3149  partexprDatum = CStringGetTextDatum(exprString);
3150  pfree(exprString);
3151  }
3152  else
3153  partexprDatum = (Datum) 0;
3154 
3155  pg_partitioned_table = heap_open(PartitionedRelationId, RowExclusiveLock);
3156 
3157  MemSet(nulls, false, sizeof(nulls));
3158 
3159  /* Only this can ever be NULL */
3160  if (!partexprDatum)
3161  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3162 
3164  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3165  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3167  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3168  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3169  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3170  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3171 
3172  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3173 
3174  CatalogTupleInsert(pg_partitioned_table, tuple);
3175  heap_close(pg_partitioned_table, RowExclusiveLock);
3176 
3177  /* Mark this relation as dependent on a few things as follows */
3178  myself.classId = RelationRelationId;
3179  myself.objectId = RelationGetRelid(rel);;
3180  myself.objectSubId = 0;
3181 
3182  /* Operator class and collation per key column */
3183  for (i = 0; i < partnatts; i++)
3184  {
3185  referenced.classId = OperatorClassRelationId;
3186  referenced.objectId = partopclass[i];
3187  referenced.objectSubId = 0;
3188 
3189  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3190 
3191  /* The default collation is pinned, so don't bother recording it */
3192  if (OidIsValid(partcollation[i]) &&
3193  partcollation[i] != DEFAULT_COLLATION_OID)
3194  {
3195  referenced.classId = CollationRelationId;
3196  referenced.objectId = partcollation[i];
3197  referenced.objectSubId = 0;
3198  }
3199 
3200  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3201  }
3202 
3203  /*
3204  * Anything mentioned in the expressions. We must ignore the column
3205  * references, which will depend on the table itself; there is no separate
3206  * partition key object.
3207  */
3208  if (partexprs)
3210  (Node *) partexprs,
3211  RelationGetRelid(rel),
3213  DEPENDENCY_AUTO, true);
3214 
3215  /*
3216  * We must invalidate the relcache so that the next
3217  * CommandCounterIncrement() will cause the same to be rebuilt using the
3218  * information in just created catalog entry.
3219  */
3221 }
Definition: c.h:544
#define RelationGetDescr(relation)
Definition: rel.h:437
#define Anum_pg_partitioned_table_partexprs
#define PointerGetDatum(X)
Definition: postgres.h:539
#define RelationRelationId
Definition: pg_class.h:29
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:110
#define Int16GetDatum(X)
Definition: postgres.h:434
#define OperatorClassRelationId
Definition: pg_opclass.h:49
Definition: nodes.h:513
#define MemSet(start, val, len)
Definition: c.h:897
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:695
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
#define OidIsValid(objectId)
Definition: c.h:594
#define Anum_pg_partitioned_table_partrelid
void pfree(void *pointer)
Definition: mcxt.c:936
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Anum_pg_partitioned_table_partcollation
#define PartitionedRelationId
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
#define RowExclusiveLock
Definition: lockdefs.h:38
#define Anum_pg_partitioned_table_partdefid
#define Anum_pg_partitioned_table_partnatts
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
Definition: c.h:533
uintptr_t Datum
Definition: postgres.h:365
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define CollationRelationId
Definition: pg_collation.h:30
#define InvalidOid
Definition: postgres_ext.h:36
#define Anum_pg_partitioned_table_partstrat
#define Assert(condition)
Definition: c.h:688
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:167
#define Natts_pg_partitioned_table
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool ignore_self)
Definition: dependency.c:1404
#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:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4281
#define Anum_pg_partitioned_table_partclass
#define Anum_pg_partitioned_table_partattrs
#define RelationGetRelid(relation)
Definition: rel.h:425

◆ SystemAttributeByName()

Form_pg_attribute SystemAttributeByName ( const char *  attname,
bool  relhasoids 
)

Definition at line 214 of file heap.c.

References lengthof, NameStr, ObjectIdAttributeNumber, and SysAtt.

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

215 {
216  int j;
217 
218  for (j = 0; j < (int) lengthof(SysAtt); j++)
219  {
220  Form_pg_attribute att = SysAtt[j];
221 
222  if (relhasoids || att->attnum != ObjectIdAttributeNumber)
223  {
224  if (strcmp(NameStr(att->attname), attname) == 0)
225  return att;
226  }
227  }
228 
229  return NULL;
230 }
static const Form_pg_attribute SysAtt[]
Definition: heap.c:192
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define lengthof(array)
Definition: c.h:618
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define NameStr(name)
Definition: c.h:565

◆ SystemAttributeDefinition()

Form_pg_attribute SystemAttributeDefinition ( AttrNumber  attno,
bool  relhasoids 
)

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

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