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

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

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

◆ CheckAttributeType()

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

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

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

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

1466 {
1467  Relation attrel;
1468  SysScanDesc scan;
1469  ScanKeyData key[1];
1470  HeapTuple atttup;
1471 
1472  /* Grab an appropriate lock on the pg_attribute relation */
1474 
1475  /* Use the index to scan only attributes of the target relation */
1476  ScanKeyInit(&key[0],
1478  BTEqualStrategyNumber, F_OIDEQ,
1479  ObjectIdGetDatum(relid));
1480 
1481  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1482  NULL, 1, key);
1483 
1484  /* Delete all the matching tuples */
1485  while ((atttup = systable_getnext(scan)) != NULL)
1486  CatalogTupleDelete(attrel, &atttup->t_self);
1487 
1488  /* Clean up after the scan */
1489  systable_endscan(scan);
1490  heap_close(attrel, RowExclusiveLock);
1491 }
#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:513
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 1436 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().

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

1503 {
1504  Relation attrel;
1505  SysScanDesc scan;
1506  ScanKeyData key[2];
1507  HeapTuple atttup;
1508 
1509  /* Grab an appropriate lock on the pg_attribute relation */
1511 
1512  /* Use the index to scan only system attributes of the target relation */
1513  ScanKeyInit(&key[0],
1515  BTEqualStrategyNumber, F_OIDEQ,
1516  ObjectIdGetDatum(relid));
1517  ScanKeyInit(&key[1],
1519  BTLessEqualStrategyNumber, F_INT2LE,
1520  Int16GetDatum(0));
1521 
1522  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1523  NULL, 2, key);
1524 
1525  /* Delete all the matching tuples */
1526  while ((atttup = systable_getnext(scan)) != NULL)
1527  CatalogTupleDelete(attrel, &atttup->t_self);
1528 
1529  /* Clean up after the scan */
1530  systable_endscan(scan);
1531  heap_close(attrel, RowExclusiveLock);
1532 }
#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:457
#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:513
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_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:
297  create_storage = false;
298 
299  /*
300  * Force reltablespace to zero if the relation has no physical
301  * storage. This is mainly just for cleanliness' sake.
302  */
303  reltablespace = InvalidOid;
304  break;
305  case RELKIND_SEQUENCE:
306  create_storage = true;
307 
308  /*
309  * Force reltablespace to zero for sequences, since we don't
310  * support moving them around into different tablespaces.
311  */
312  reltablespace = InvalidOid;
313  break;
314  default:
315  create_storage = true;
316  break;
317  }
318 
319  /*
320  * Unless otherwise requested, the physical ID (relfilenode) is initially
321  * the same as the logical ID (OID). When the caller did specify a
322  * relfilenode, it already exists; do not attempt to create it.
323  */
324  if (OidIsValid(relfilenode))
325  create_storage = false;
326  else
327  relfilenode = relid;
328 
329  /*
330  * Never allow a pg_class entry to explicitly specify the database's
331  * default tablespace in reltablespace; force it to zero instead. This
332  * ensures that if the database is cloned with a different default
333  * tablespace, the pg_class entry will still match where CREATE DATABASE
334  * will put the physically copied relation.
335  *
336  * Yes, this is a bit of a hack.
337  */
338  if (reltablespace == MyDatabaseTableSpace)
339  reltablespace = InvalidOid;
340 
341  /*
342  * build the relcache entry.
343  */
344  rel = RelationBuildLocalRelation(relname,
345  relnamespace,
346  tupDesc,
347  relid,
348  relfilenode,
349  reltablespace,
350  shared_relation,
351  mapped_relation,
352  relpersistence,
353  relkind);
354 
355  /*
356  * Have the storage manager create the relation's disk file, if needed.
357  *
358  * We only create the main fork here, other forks will be created on
359  * demand.
360  */
361  if (create_storage)
362  {
363  RelationOpenSmgr(rel);
364  RelationCreateStorage(rel->rd_node, relpersistence);
365  }
366 
367  return rel;
368 }
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:3190
int errcode(int sqlerrcode)
Definition: elog.c:575
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:177
#define OidIsValid(objectId)
Definition: c.h:576
#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:3066
#define IsNormalProcessingMode()
Definition: miscadmin.h:369
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_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:670
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 1382 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().

1383 {
1384  Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
1385  rel->rd_rel->relkind == RELKIND_MATVIEW ||
1386  rel->rd_rel->relkind == RELKIND_TOASTVALUE);
1387  RelationOpenSmgr(rel);
1388  smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
1391 }
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:670
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 1021 of file heap.c.

References ACL_OBJECT_RELATION, ACL_OBJECT_SEQUENCE, 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, 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().

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

◆ heap_drop_with_catalog()

void heap_drop_with_catalog ( Oid  relid)

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

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

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

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

◆ heap_truncate_find_FKs()

List* heap_truncate_find_FKs ( List relationIds)

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

3031 {
3032  List *result = NIL;
3033  Relation fkeyRel;
3034  SysScanDesc fkeyScan;
3035  HeapTuple tuple;
3036 
3037  /*
3038  * Must scan pg_constraint. Right now, it is a seqscan because there is
3039  * no available index on confrelid.
3040  */
3042 
3043  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3044  NULL, 0, NULL);
3045 
3046  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3047  {
3049 
3050  /* Not a foreign key */
3051  if (con->contype != CONSTRAINT_FOREIGN)
3052  continue;
3053 
3054  /* Not referencing one of our list of tables */
3055  if (!list_member_oid(relationIds, con->confrelid))
3056  continue;
3057 
3058  /* Add referencer unless already in input or result list */
3059  if (!list_member_oid(relationIds, con->conrelid))
3060  result = insert_ordered_unique_oid(result, con->conrelid);
3061  }
3062 
3063  systable_endscan(fkeyScan);
3064  heap_close(fkeyRel, AccessShareLock);
3065 
3066  return result;
3067 }
#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:3080
#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 2901 of file heap.c.

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

Referenced by ExecuteTruncate(), and heap_truncate().

2902 {
2903  Oid toastrelid;
2904 
2905  /* Truncate the actual file (and discard buffers) */
2906  RelationTruncate(rel, 0);
2907 
2908  /* If the relation has indexes, truncate the indexes too */
2910 
2911  /* If there is a toast table, truncate that too */
2912  toastrelid = rel->rd_rel->reltoastrelid;
2913  if (OidIsValid(toastrelid))
2914  {
2915  Relation toastrel = heap_open(toastrelid, AccessExclusiveLock);
2916 
2917  RelationTruncate(toastrel, 0);
2918  RelationTruncateIndexes(toastrel);
2919  /* keep the lock... */
2920  heap_close(toastrel, NoLock);
2921  }
2922 }
#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:576
#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:2819
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 600 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().

603 {
605  bool nulls[Natts_pg_attribute];
606  HeapTuple tup;
607 
608  /* This is a tad tedious, but way cleaner than what we used to do... */
609  memset(values, 0, sizeof(values));
610  memset(nulls, false, sizeof(nulls));
611 
612  values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
613  values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
614  values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
615  values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
616  values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
617  values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
618  values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
619  values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(new_attribute->attcacheoff);
620  values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
621  values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
622  values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
623  values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
624  values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
625  values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
626  values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
627  values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
628  values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
629  values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
630  values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
631 
632  /* start out with empty permissions and empty options */
633  nulls[Anum_pg_attribute_attacl - 1] = true;
634  nulls[Anum_pg_attribute_attoptions - 1] = true;
635  nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
636 
637  tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
638 
639  /* finally insert the new tuple, update the indexes, and clean up */
640  if (indstate != NULL)
641  CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
642  else
643  CatalogTupleInsert(pg_attribute_rel, tup);
644 
645  heap_freetuple(tup);
646 }
#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:601
#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:457
#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:513
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:372
#define Anum_pg_attribute_attalign
Definition: pg_attribute.h:206
#define BoolGetDatum(X)
Definition: postgres.h:408
#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:422
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define Int32GetDatum(X)
Definition: postgres.h:485
#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 766 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().

771 {
772  Form_pg_class rd_rel = new_rel_desc->rd_rel;
774  bool nulls[Natts_pg_class];
775  HeapTuple tup;
776 
777  /* This is a tad tedious, but way cleaner than what we used to do... */
778  memset(values, 0, sizeof(values));
779  memset(nulls, false, sizeof(nulls));
780 
781  values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
782  values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
783  values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
784  values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
785  values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
786  values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
787  values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
788  values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
789  values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
790  values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
791  values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
792  values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
793  values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
794  values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
795  values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
796  values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
797  values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
798  values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
799  values[Anum_pg_class_relhasoids - 1] = BoolGetDatum(rd_rel->relhasoids);
800  values[Anum_pg_class_relhaspkey - 1] = BoolGetDatum(rd_rel->relhaspkey);
801  values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
802  values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
803  values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
804  values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
805  values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
806  values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
807  values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
808  values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
809  values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
810  values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
811  if (relacl != (Datum) 0)
812  values[Anum_pg_class_relacl - 1] = relacl;
813  else
814  nulls[Anum_pg_class_relacl - 1] = true;
815  if (reloptions != (Datum) 0)
816  values[Anum_pg_class_reloptions - 1] = reloptions;
817  else
818  nulls[Anum_pg_class_reloptions - 1] = true;
819 
820  /* relpartbound is set by updating this tuple, if necessary */
821  nulls[Anum_pg_class_relpartbound - 1] = true;
822 
823  tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
824 
825  /*
826  * The new tuple must have the oid already chosen for the rel. Sure would
827  * be embarrassing to do this sort of thing in polite company.
828  */
829  HeapTupleSetOid(tup, new_rel_oid);
830 
831  /* finally insert the new tuple, update the indexes, and clean up */
832  CatalogTupleInsert(pg_class_desc, tup);
833 
834  heap_freetuple(tup);
835 }
#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:601
#define Anum_pg_class_relacl
Definition: pg_class.h:133
#define MultiXactIdGetDatum(X)
Definition: postgres.h:534
#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:457
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:513
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:527
#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:372
#define Anum_pg_class_reltuples
Definition: pg_class.h:112
#define BoolGetDatum(X)
Definition: postgres.h:408
#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:422
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:485
#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 1631 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().

1633 {
1634  Relation attrdef_rel;
1635  ScanKeyData scankeys[2];
1636  SysScanDesc scan;
1637  HeapTuple tuple;
1638  bool found = false;
1639 
1641 
1642  ScanKeyInit(&scankeys[0],
1644  BTEqualStrategyNumber, F_OIDEQ,
1645  ObjectIdGetDatum(relid));
1646  ScanKeyInit(&scankeys[1],
1648  BTEqualStrategyNumber, F_INT2EQ,
1649  Int16GetDatum(attnum));
1650 
1651  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1652  NULL, 2, scankeys);
1653 
1654  /* There should be at most one matching tuple, but we loop anyway */
1655  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1656  {
1657  ObjectAddress object;
1658 
1659  object.classId = AttrDefaultRelationId;
1660  object.objectId = HeapTupleGetOid(tuple);
1661  object.objectSubId = 0;
1662 
1663  performDeletion(&object, behavior,
1664  internal ? PERFORM_DELETION_INTERNAL : 0);
1665 
1666  found = true;
1667  }
1668 
1669  systable_endscan(scan);
1670  heap_close(attrdef_rel, RowExclusiveLock);
1671 
1672  if (complain && !found)
1673  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1674  relid, attnum);
1675 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define Int16GetDatum(X)
Definition: postgres.h:457
#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:513
#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:174

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

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

1686 {
1687  Relation attrdef_rel;
1688  Relation attr_rel;
1689  Relation myrel;
1690  ScanKeyData scankeys[1];
1691  SysScanDesc scan;
1692  HeapTuple tuple;
1693  Oid myrelid;
1694  AttrNumber myattnum;
1695 
1696  /* Grab an appropriate lock on the pg_attrdef relation */
1698 
1699  /* Find the pg_attrdef tuple */
1700  ScanKeyInit(&scankeys[0],
1702  BTEqualStrategyNumber, F_OIDEQ,
1703  ObjectIdGetDatum(attrdefId));
1704 
1705  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1706  NULL, 1, scankeys);
1707 
1708  tuple = systable_getnext(scan);
1709  if (!HeapTupleIsValid(tuple))
1710  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1711 
1712  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1713  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1714 
1715  /* Get an exclusive lock on the relation owning the attribute */
1716  myrel = relation_open(myrelid, AccessExclusiveLock);
1717 
1718  /* Now we can delete the pg_attrdef row */
1719  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1720 
1721  systable_endscan(scan);
1722  heap_close(attrdef_rel, RowExclusiveLock);
1723 
1724  /* Fix the pg_attribute row */
1726 
1727  tuple = SearchSysCacheCopy2(ATTNUM,
1728  ObjectIdGetDatum(myrelid),
1729  Int16GetDatum(myattnum));
1730  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1731  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1732  myattnum, myrelid);
1733 
1734  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1735 
1736  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1737 
1738  /*
1739  * Our update of the pg_attribute row will force a relcache rebuild, so
1740  * there's nothing else to do here.
1741  */
1742  heap_close(attr_rel, RowExclusiveLock);
1743 
1744  /* Keep lock on attribute's rel until end of xact */
1745  relation_close(myrel, NoLock);
1746 }
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:457
#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:513
#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 1543 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().

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

3227 {
3228  Relation rel;
3229  HeapTuple tuple;
3230 
3232 
3233  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3234  if (!HeapTupleIsValid(tuple))
3235  elog(ERROR, "cache lookup failed for partition key of relation %u",
3236  relid);
3237 
3238  CatalogTupleDelete(rel, &tuple->t_self);
3239 
3240  ReleaseSysCache(tuple);
3242 }
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:513
#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 2772 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().

2773 {
2774  Relation pgstatistic;
2775  SysScanDesc scan;
2776  ScanKeyData key[2];
2777  int nkeys;
2778  HeapTuple tuple;
2779 
2781 
2782  ScanKeyInit(&key[0],
2784  BTEqualStrategyNumber, F_OIDEQ,
2785  ObjectIdGetDatum(relid));
2786 
2787  if (attnum == 0)
2788  nkeys = 1;
2789  else
2790  {
2791  ScanKeyInit(&key[1],
2793  BTEqualStrategyNumber, F_INT2EQ,
2794  Int16GetDatum(attnum));
2795  nkeys = 2;
2796  }
2797 
2798  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
2799  NULL, nkeys, key);
2800 
2801  /* we must loop even when attnum != 0, in case of inherited stats */
2802  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
2803  CatalogTupleDelete(pgstatistic, &tuple->t_self);
2804 
2805  systable_endscan(scan);
2806 
2807  heap_close(pgstatistic, RowExclusiveLock);
2808 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define Int16GetDatum(X)
Definition: postgres.h:457
#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:513
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 1929 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().

1931 {
1932  char *adbin;
1933  char *adsrc;
1934  Relation adrel;
1935  HeapTuple tuple;
1936  Datum values[4];
1937  static bool nulls[4] = {false, false, false, false};
1938  Relation attrrel;
1939  HeapTuple atttup;
1940  Form_pg_attribute attStruct;
1941  Oid attrdefOid;
1942  ObjectAddress colobject,
1943  defobject;
1944 
1945  /*
1946  * Flatten expression to string form for storage.
1947  */
1948  adbin = nodeToString(expr);
1949 
1950  /*
1951  * Also deparse it to form the mostly-obsolete adsrc field.
1952  */
1953  adsrc = deparse_expression(expr,
1955  RelationGetRelid(rel)),
1956  false, false);
1957 
1958  /*
1959  * Make the pg_attrdef entry.
1960  */
1961  values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
1962  values[Anum_pg_attrdef_adnum - 1] = attnum;
1963  values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
1964  values[Anum_pg_attrdef_adsrc - 1] = CStringGetTextDatum(adsrc);
1965 
1967 
1968  tuple = heap_form_tuple(adrel->rd_att, values, nulls);
1969  attrdefOid = CatalogTupleInsert(adrel, tuple);
1970 
1971  defobject.classId = AttrDefaultRelationId;
1972  defobject.objectId = attrdefOid;
1973  defobject.objectSubId = 0;
1974 
1975  heap_close(adrel, RowExclusiveLock);
1976 
1977  /* now can free some of the stuff allocated above */
1980  heap_freetuple(tuple);
1981  pfree(adbin);
1982  pfree(adsrc);
1983 
1984  /*
1985  * Update the pg_attribute entry for the column to show that a default
1986  * exists.
1987  */
1989  atttup = SearchSysCacheCopy2(ATTNUM,
1991  Int16GetDatum(attnum));
1992  if (!HeapTupleIsValid(atttup))
1993  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1994  attnum, RelationGetRelid(rel));
1995  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
1996  if (!attStruct->atthasdef)
1997  {
1998  attStruct->atthasdef = true;
1999  CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
2000  }
2001  heap_close(attrrel, RowExclusiveLock);
2002  heap_freetuple(atttup);
2003 
2004  /*
2005  * Make a dependency so that the pg_attrdef entry goes away if the column
2006  * (or whole table) is deleted.
2007  */
2008  colobject.classId = RelationRelationId;
2009  colobject.objectId = RelationGetRelid(rel);
2010  colobject.objectSubId = attnum;
2011 
2012  recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
2013 
2014  /*
2015  * Record dependencies on objects used in the expression, too.
2016  */
2017  recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
2018 
2019  /*
2020  * Post creation hook for attribute defaults.
2021  *
2022  * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
2023  * couple of deletion/creation of the attribute's default entry, so the
2024  * callee should check existence of an older version of this entry if it
2025  * needs to distinguish.
2026  */
2028  RelationGetRelid(rel), attnum, is_internal);
2029 
2030  return attrdefOid;
2031 }
#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:457
#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:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:3067
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1351
#define RelationGetRelationName(relation)
Definition: rel.h:445
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
uintptr_t Datum
Definition: postgres.h:372
#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:3008
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
#define DatumGetPointer(X)
Definition: postgres.h:555
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4265
#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 3254 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().

3255 {
3256  Relation classRel;
3257  HeapTuple tuple,
3258  newtuple;
3259  Datum new_val[Natts_pg_class];
3260  bool new_null[Natts_pg_class],
3261  new_repl[Natts_pg_class];
3262  Oid defaultPartOid;
3263 
3264  /* Update pg_class tuple */
3266  tuple = SearchSysCacheCopy1(RELOID,
3268  if (!HeapTupleIsValid(tuple))
3269  elog(ERROR, "cache lookup failed for relation %u",
3270  RelationGetRelid(rel));
3271 
3272 #ifdef USE_ASSERT_CHECKING
3273  {
3274  Form_pg_class classForm;
3275  bool isnull;
3276 
3277  classForm = (Form_pg_class) GETSTRUCT(tuple);
3278  Assert(!classForm->relispartition);
3280  &isnull);
3281  Assert(isnull);
3282  }
3283 #endif
3284 
3285  /* Fill in relpartbound value */
3286  memset(new_val, 0, sizeof(new_val));
3287  memset(new_null, false, sizeof(new_null));
3288  memset(new_repl, false, sizeof(new_repl));
3290  new_null[Anum_pg_class_relpartbound - 1] = false;
3291  new_repl[Anum_pg_class_relpartbound - 1] = true;
3292  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3293  new_val, new_null, new_repl);
3294  /* Also set the flag */
3295  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3296  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3297  heap_freetuple(newtuple);
3298  heap_close(classRel, RowExclusiveLock);
3299 
3300  /*
3301  * The partition constraint for the default partition depends on the
3302  * partition bounds of every other partition, so we must invalidate the
3303  * relcache entry for that partition every time a partition is added or
3304  * removed.
3305  */
3306  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3307  if (OidIsValid(defaultPartOid))
3308  CacheInvalidateRelcacheByRelid(defaultPartOid);
3309 
3310  CacheInvalidateRelcache(parent);
3311 }
#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:576
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#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:372
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:670
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:4265
#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:2911
#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 3114 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().

3121 {
3122  int i;
3123  int2vector *partattrs_vec;
3124  oidvector *partopclass_vec;
3125  oidvector *partcollation_vec;
3126  Datum partexprDatum;
3127  Relation pg_partitioned_table;
3128  HeapTuple tuple;
3130  bool nulls[Natts_pg_partitioned_table];
3131  ObjectAddress myself;
3132  ObjectAddress referenced;
3133 
3134  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3135 
3136  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3137  partattrs_vec = buildint2vector(partattrs, partnatts);
3138  partopclass_vec = buildoidvector(partopclass, partnatts);
3139  partcollation_vec = buildoidvector(partcollation, partnatts);
3140 
3141  /* Convert the expressions (if any) to a text datum */
3142  if (partexprs)
3143  {
3144  char *exprString;
3145 
3146  exprString = nodeToString(partexprs);
3147  partexprDatum = CStringGetTextDatum(exprString);
3148  pfree(exprString);
3149  }
3150  else
3151  partexprDatum = (Datum) 0;
3152 
3153  pg_partitioned_table = heap_open(PartitionedRelationId, RowExclusiveLock);
3154 
3155  MemSet(nulls, false, sizeof(nulls));
3156 
3157  /* Only this can ever be NULL */
3158  if (!partexprDatum)
3159  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3160 
3162  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3163  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3165  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3166  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3167  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3168  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3169 
3170  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3171 
3172  CatalogTupleInsert(pg_partitioned_table, tuple);
3173  heap_close(pg_partitioned_table, RowExclusiveLock);
3174 
3175  /* Mark this relation as dependent on a few things as follows */
3176  myself.classId = RelationRelationId;
3177  myself.objectId = RelationGetRelid(rel);;
3178  myself.objectSubId = 0;
3179 
3180  /* Operator class and collation per key column */
3181  for (i = 0; i < partnatts; i++)
3182  {
3183  referenced.classId = OperatorClassRelationId;
3184  referenced.objectId = partopclass[i];
3185  referenced.objectSubId = 0;
3186 
3187  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3188 
3189  /* The default collation is pinned, so don't bother recording it */
3190  if (OidIsValid(partcollation[i]) &&
3191  partcollation[i] != DEFAULT_COLLATION_OID)
3192  {
3193  referenced.classId = CollationRelationId;
3194  referenced.objectId = partcollation[i];
3195  referenced.objectSubId = 0;
3196  }
3197 
3198  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3199  }
3200 
3201  /*
3202  * Anything mentioned in the expressions. We must ignore the column
3203  * references, which will depend on the table itself; there is no separate
3204  * partition key object.
3205  */
3206  if (partexprs)
3208  (Node *) partexprs,
3209  RelationGetRelid(rel),
3211  DEPENDENCY_AUTO, true);
3212 
3213  /*
3214  * We must invalidate the relcache so that the next
3215  * CommandCounterIncrement() will cause the same to be rebuilt using the
3216  * information in just created catalog entry.
3217  */
3219 }
Definition: c.h:526
#define RelationGetDescr(relation)
Definition: rel.h:437
#define Anum_pg_partitioned_table_partexprs
#define PointerGetDatum(X)
Definition: postgres.h:562
#define RelationRelationId
Definition: pg_class.h:29
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:112
#define Int16GetDatum(X)
Definition: postgres.h:457
#define OperatorClassRelationId
Definition: pg_opclass.h:49
Definition: nodes.h:512
#define MemSet(start, val, len)
Definition: c.h:853
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:576
#define Anum_pg_partitioned_table_partrelid
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
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:515
uintptr_t Datum
Definition: postgres.h:372
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:670
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:1392
#define CharGetDatum(X)
Definition: postgres.h:422
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:4265
#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(), 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:600
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define NameStr(name)
Definition: c.h:547

◆ 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:600
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219