PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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, 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)
 
void RemoveStatisticsExt (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, Node *bound)
 

Typedef Documentation

Function Documentation

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

Definition at line 2197 of file heap.c.

References addRangeTableEntryForRelation(), addRTEtoQuery(), Assert, RawColumnDefault::attnum, CookedConstraint::attnum, tupleDesc::attrs, 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, NULL, 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(), and stringToNode().

Referenced by ATAddCheckConstraint(), ATExecAddColumn(), ATExecColumnDefault(), and DefineRelation().

2203 {
2204  List *cookedConstraints = NIL;
2206  TupleConstr *oldconstr;
2207  int numoldchecks;
2208  ParseState *pstate;
2209  RangeTblEntry *rte;
2210  int numchecks;
2211  List *checknames;
2212  ListCell *cell;
2213  Node *expr;
2214  CookedConstraint *cooked;
2215 
2216  /*
2217  * Get info about existing constraints.
2218  */
2219  tupleDesc = RelationGetDescr(rel);
2220  oldconstr = tupleDesc->constr;
2221  if (oldconstr)
2222  numoldchecks = oldconstr->num_check;
2223  else
2224  numoldchecks = 0;
2225 
2226  /*
2227  * Create a dummy ParseState and insert the target relation as its sole
2228  * rangetable entry. We need a ParseState for transformExpr.
2229  */
2230  pstate = make_parsestate(NULL);
2231  rte = addRangeTableEntryForRelation(pstate,
2232  rel,
2233  NULL,
2234  false,
2235  true);
2236  addRTEtoQuery(pstate, rte, true, true, true);
2237 
2238  /*
2239  * Process column default expressions.
2240  */
2241  foreach(cell, newColDefaults)
2242  {
2243  RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
2244  Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
2245  Oid defOid;
2246 
2247  expr = cookDefault(pstate, colDef->raw_default,
2248  atp->atttypid, atp->atttypmod,
2249  NameStr(atp->attname));
2250 
2251  /*
2252  * If the expression is just a NULL constant, we do not bother to make
2253  * an explicit pg_attrdef entry, since the default behavior is
2254  * equivalent.
2255  *
2256  * Note a nonobvious property of this test: if the column is of a
2257  * domain type, what we'll get is not a bare null Const but a
2258  * CoerceToDomain expr, so we will not discard the default. This is
2259  * critical because the column default needs to be retained to
2260  * override any default that the domain might have.
2261  */
2262  if (expr == NULL ||
2263  (IsA(expr, Const) &&((Const *) expr)->constisnull))
2264  continue;
2265 
2266  defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
2267 
2268  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2269  cooked->contype = CONSTR_DEFAULT;
2270  cooked->conoid = defOid;
2271  cooked->name = NULL;
2272  cooked->attnum = colDef->attnum;
2273  cooked->expr = expr;
2274  cooked->skip_validation = false;
2275  cooked->is_local = is_local;
2276  cooked->inhcount = is_local ? 0 : 1;
2277  cooked->is_no_inherit = false;
2278  cookedConstraints = lappend(cookedConstraints, cooked);
2279  }
2280 
2281  /*
2282  * Process constraint expressions.
2283  */
2284  numchecks = numoldchecks;
2285  checknames = NIL;
2286  foreach(cell, newConstraints)
2287  {
2288  Constraint *cdef = (Constraint *) lfirst(cell);
2289  char *ccname;
2290  Oid constrOid;
2291 
2292  if (cdef->contype != CONSTR_CHECK)
2293  continue;
2294 
2295  if (cdef->raw_expr != NULL)
2296  {
2297  Assert(cdef->cooked_expr == NULL);
2298 
2299  /*
2300  * Transform raw parsetree to executable expression, and verify
2301  * it's valid as a CHECK constraint.
2302  */
2303  expr = cookConstraint(pstate, cdef->raw_expr,
2305  }
2306  else
2307  {
2308  Assert(cdef->cooked_expr != NULL);
2309 
2310  /*
2311  * Here, we assume the parser will only pass us valid CHECK
2312  * expressions, so we do no particular checking.
2313  */
2314  expr = stringToNode(cdef->cooked_expr);
2315  }
2316 
2317  /*
2318  * Check name uniqueness, or generate a name if none was given.
2319  */
2320  if (cdef->conname != NULL)
2321  {
2322  ListCell *cell2;
2323 
2324  ccname = cdef->conname;
2325  /* Check against other new constraints */
2326  /* Needed because we don't do CommandCounterIncrement in loop */
2327  foreach(cell2, checknames)
2328  {
2329  if (strcmp((char *) lfirst(cell2), ccname) == 0)
2330  ereport(ERROR,
2332  errmsg("check constraint \"%s\" already exists",
2333  ccname)));
2334  }
2335 
2336  /* save name for future checks */
2337  checknames = lappend(checknames, ccname);
2338 
2339  /*
2340  * Check against pre-existing constraints. If we are allowed to
2341  * merge with an existing constraint, there's no more to do here.
2342  * (We omit the duplicate constraint from the result, which is
2343  * what ATAddCheckConstraint wants.)
2344  */
2345  if (MergeWithExistingConstraint(rel, ccname, expr,
2346  allow_merge, is_local,
2347  cdef->initially_valid,
2348  cdef->is_no_inherit))
2349  continue;
2350  }
2351  else
2352  {
2353  /*
2354  * When generating a name, we want to create "tab_col_check" for a
2355  * column constraint and "tab_check" for a table constraint. We
2356  * no longer have any info about the syntactic positioning of the
2357  * constraint phrase, so we approximate this by seeing whether the
2358  * expression references more than one column. (If the user
2359  * played by the rules, the result is the same...)
2360  *
2361  * Note: pull_var_clause() doesn't descend into sublinks, but we
2362  * eliminated those above; and anyway this only needs to be an
2363  * approximate answer.
2364  */
2365  List *vars;
2366  char *colname;
2367 
2368  vars = pull_var_clause(expr, 0);
2369 
2370  /* eliminate duplicates */
2371  vars = list_union(NIL, vars);
2372 
2373  if (list_length(vars) == 1)
2374  colname = get_attname(RelationGetRelid(rel),
2375  ((Var *) linitial(vars))->varattno);
2376  else
2377  colname = NULL;
2378 
2380  colname,
2381  "check",
2382  RelationGetNamespace(rel),
2383  checknames);
2384 
2385  /* save name for future checks */
2386  checknames = lappend(checknames, ccname);
2387  }
2388 
2389  /*
2390  * OK, store it.
2391  */
2392  constrOid =
2393  StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
2394  is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
2395 
2396  numchecks++;
2397 
2398  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2399  cooked->contype = CONSTR_CHECK;
2400  cooked->conoid = constrOid;
2401  cooked->name = ccname;
2402  cooked->attnum = 0;
2403  cooked->expr = expr;
2404  cooked->skip_validation = cdef->skip_validation;
2405  cooked->is_local = is_local;
2406  cooked->inhcount = is_local ? 0 : 1;
2407  cooked->is_no_inherit = cdef->is_no_inherit;
2408  cookedConstraints = lappend(cookedConstraints, cooked);
2409  }
2410 
2411  /*
2412  * Update the count of constraints in the relation's pg_class tuple. We do
2413  * this even if there was no change, in order to ensure that an SI update
2414  * message is sent out for the pg_class tuple, which will force other
2415  * backends to rebuild their relcache entries for the rel. (This is
2416  * critical if we added defaults but not constraints.)
2417  */
2418  SetRelationNumChecks(rel, numchecks);
2419 
2420  return cookedConstraints;
2421 }
#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:573
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2584
bool is_no_inherit
Definition: heap.h:38
AttrNumber attnum
Definition: heap.h:24
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, char *attname)
Definition: heap.c:2627
#define RelationGetDescr(relation)
Definition: rel.h:429
static Oid StoreRelCheck(Relation rel, char *ccname, Node *expr, bool is_validated, bool is_local, int inhcount, bool is_no_inherit, bool is_internal)
Definition: heap.c:2010
Node * raw_expr
Definition: parsenodes.h:2035
static Node * cookConstraint(ParseState *pstate, Node *raw_constraint, char *relname)
Definition: heap.c:2698
Form_pg_attribute * attrs
Definition: tupdesc.h:74
Definition: nodes.h:522
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:2028
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
AttrNumber attnum
Definition: heap.h:33
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
static bool MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr, bool allow_merge, bool is_local, bool is_initially_valid, bool is_no_inherit)
Definition: heap.c:2434
int inhcount
Definition: heap.h:37
#define RelationGetRelationName(relation)
Definition: rel.h:437
Node * raw_default
Definition: heap.h:25
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:184
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
TupleDesc rd_att
Definition: rel.h:115
bool is_no_inherit
Definition: parsenodes.h:2034
bool initially_valid
Definition: parsenodes.h:2064
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
TupleConstr * constr
Definition: tupdesc.h:76
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:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid conoid
Definition: heap.h:31
#define NameStr(name)
Definition: c.h:499
ConstrType contype
Definition: parsenodes.h:2025
Node * expr
Definition: heap.h:34
uint16 num_check
Definition: tupdesc.h:42
char * cooked_expr
Definition: parsenodes.h:2036
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal)
Definition: heap.c:1897
Definition: regcomp.c:224
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
Definition: pg_list.h:45
bool skip_validation
Definition: parsenodes.h:2063
char * name
Definition: heap.h:32
#define RelationGetRelid(relation)
Definition: rel.h:417
bool is_local
Definition: heap.h:36
#define RelationGetNamespace(relation)
Definition: rel.h:444
void CheckAttributeNamesTypes ( TupleDesc  tupdesc,
char  relkind,
bool  allow_system_table_mods 
)

Definition at line 409 of file heap.c.

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

Referenced by addRangeTableEntryForFunction(), and heap_create_with_catalog().

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

Definition at line 487 of file heap.c.

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

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

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

Definition at line 2627 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(), NULL, OidIsValid, and transformExpr().

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

2632 {
2633  Node *expr;
2634 
2635  Assert(raw_default != NULL);
2636 
2637  /*
2638  * Transform raw parsetree to executable expression.
2639  */
2640  expr = transformExpr(pstate, raw_default, EXPR_KIND_COLUMN_DEFAULT);
2641 
2642  /*
2643  * Make sure default expr does not refer to any vars (we need this check
2644  * since the pstate includes the target table).
2645  */
2646  if (contain_var_clause(expr))
2647  ereport(ERROR,
2648  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2649  errmsg("cannot use column references in default expression")));
2650 
2651  /*
2652  * transformExpr() should have already rejected subqueries, aggregates,
2653  * window functions, and SRFs, based on the EXPR_KIND_ for a default
2654  * expression.
2655  */
2656 
2657  /*
2658  * Coerce the expression to the correct type and typmod, if given. This
2659  * should match the parser's processing of non-defaulted expressions ---
2660  * see transformAssignedExpr().
2661  */
2662  if (OidIsValid(atttypid))
2663  {
2664  Oid type_id = exprType(expr);
2665 
2666  expr = coerce_to_target_type(pstate, expr, type_id,
2667  atttypid, atttypmod,
2670  -1);
2671  if (expr == NULL)
2672  ereport(ERROR,
2673  (errcode(ERRCODE_DATATYPE_MISMATCH),
2674  errmsg("column \"%s\" is of type %s"
2675  " but default expression is of type %s",
2676  attname,
2677  format_type_be(atttypid),
2678  format_type_be(type_id)),
2679  errhint("You will need to rewrite or cast the expression.")));
2680  }
2681 
2682  /*
2683  * Finally, take care of collations in the finished expression.
2684  */
2685  assign_expr_collations(pstate, expr);
2686 
2687  return expr;
2688 }
int errhint(const char *fmt,...)
Definition: elog.c:987
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:147
Definition: nodes.h:522
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:538
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:77
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int errmsg(const char *fmt,...)
Definition: elog.c:797
void DeleteAttributeTuples ( Oid  relid)

Definition at line 1459 of file heap.c.

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

Referenced by heap_drop_with_catalog(), and index_drop().

1460 {
1461  Relation attrel;
1462  SysScanDesc scan;
1463  ScanKeyData key[1];
1464  HeapTuple atttup;
1465 
1466  /* Grab an appropriate lock on the pg_attribute relation */
1468 
1469  /* Use the index to scan only attributes of the target relation */
1470  ScanKeyInit(&key[0],
1472  BTEqualStrategyNumber, F_OIDEQ,
1473  ObjectIdGetDatum(relid));
1474 
1475  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1476  NULL, 1, key);
1477 
1478  /* Delete all the matching tuples */
1479  while ((atttup = systable_getnext(scan)) != NULL)
1480  CatalogTupleDelete(attrel, &atttup->t_self);
1481 
1482  /* Clean up after the scan */
1483  systable_endscan(scan);
1484  heap_close(attrel, RowExclusiveLock);
1485 }
#define AttributeRelidNumIndexId
Definition: indexing.h:94
#define Anum_pg_attribute_attrelid
Definition: pg_attribute.h:192
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:1287
#define NULL
Definition: c.h:229
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void DeleteRelationTuple ( Oid  relid)

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

1431 {
1432  Relation pg_class_desc;
1433  HeapTuple tup;
1434 
1435  /* Grab an appropriate lock on the pg_class relation */
1436  pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);
1437 
1438  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1439  if (!HeapTupleIsValid(tup))
1440  elog(ERROR, "cache lookup failed for relation %u", relid);
1441 
1442  /* delete the relation tuple from pg_class, and finish up */
1443  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1444 
1445  ReleaseSysCache(tup);
1446 
1447  heap_close(pg_class_desc, RowExclusiveLock);
1448 }
#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 SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#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 ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219
void DeleteSystemAttributeTuples ( Oid  relid)

Definition at line 1496 of file heap.c.

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

Referenced by DefineQueryRewrite().

1497 {
1498  Relation attrel;
1499  SysScanDesc scan;
1500  ScanKeyData key[2];
1501  HeapTuple atttup;
1502 
1503  /* Grab an appropriate lock on the pg_attribute relation */
1505 
1506  /* Use the index to scan only system attributes of the target relation */
1507  ScanKeyInit(&key[0],
1509  BTEqualStrategyNumber, F_OIDEQ,
1510  ObjectIdGetDatum(relid));
1511  ScanKeyInit(&key[1],
1513  BTLessEqualStrategyNumber, F_INT2LE,
1514  Int16GetDatum(0));
1515 
1516  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1517  NULL, 2, key);
1518 
1519  /* Delete all the matching tuples */
1520  while ((atttup = systable_getnext(scan)) != NULL)
1521  CatalogTupleDelete(attrel, &atttup->t_self);
1522 
1523  /* Clean up after the scan */
1524  systable_endscan(scan);
1525  heap_close(attrel, RowExclusiveLock);
1526 }
#define AttributeRelidNumIndexId
Definition: indexing.h:94
#define Anum_pg_attribute_attrelid
Definition: pg_attribute.h:192
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define Anum_pg_attribute_attnum
Definition: pg_attribute.h:197
#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:1287
#define NULL
Definition: c.h:229
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
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_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:
296  create_storage = false;
297 
298  /*
299  * Force reltablespace to zero if the relation has no physical
300  * storage. This is mainly just for cleanliness' sake.
301  */
302  reltablespace = InvalidOid;
303  break;
304  case RELKIND_SEQUENCE:
305  create_storage = true;
306 
307  /*
308  * Force reltablespace to zero for sequences, since we don't
309  * support moving them around into different tablespaces.
310  */
311  reltablespace = InvalidOid;
312  break;
313  default:
314  create_storage = true;
315  break;
316  }
317 
318  /*
319  * Unless otherwise requested, the physical ID (relfilenode) is initially
320  * the same as the logical ID (OID). When the caller did specify a
321  * relfilenode, it already exists; do not attempt to create it.
322  */
323  if (OidIsValid(relfilenode))
324  create_storage = false;
325  else
326  relfilenode = relid;
327 
328  /*
329  * Never allow a pg_class entry to explicitly specify the database's
330  * default tablespace in reltablespace; force it to zero instead. This
331  * ensures that if the database is cloned with a different default
332  * tablespace, the pg_class entry will still match where CREATE DATABASE
333  * will put the physically copied relation.
334  *
335  * Yes, this is a bit of a hack.
336  */
337  if (reltablespace == MyDatabaseTableSpace)
338  reltablespace = InvalidOid;
339 
340  /*
341  * build the relcache entry.
342  */
343  rel = RelationBuildLocalRelation(relname,
344  relnamespace,
345  tupDesc,
346  relid,
347  relfilenode,
348  reltablespace,
349  shared_relation,
350  mapped_relation,
351  relpersistence,
352  relkind);
353 
354  /*
355  * Have the storage manager create the relation's disk file, if needed.
356  *
357  * We only create the main fork here, other forks will be created on
358  * demand.
359  */
360  if (create_storage)
361  {
362  RelationOpenSmgr(rel);
363  RelationCreateStorage(rel->rd_node, relpersistence);
364  }
365 
366  return rel;
367 }
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:3179
int errcode(int sqlerrcode)
Definition: elog.c:575
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:176
#define OidIsValid(objectId)
Definition: c.h:538
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
Oid MyDatabaseTableSpace
Definition: globals.c:78
#define RelationOpenSmgr(relation)
Definition: rel.h:461
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
#define IsNormalProcessingMode()
Definition: miscadmin.h:367
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
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:162
#define InvalidOid
Definition: postgres_ext.h:36
RelFileNode rd_node
Definition: rel.h:85
#define Assert(condition)
Definition: c.h:675
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
void heap_create_init_fork ( Relation  rel)

Definition at line 1379 of file heap.c.

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

Referenced by ExecuteTruncate(), and heap_create_with_catalog().

1380 {
1381  RelationOpenSmgr(rel);
1382  smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
1385 }
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:376
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
#define RelationOpenSmgr(relation)
Definition: rel.h:461
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
RelFileNode node
Definition: relfilenode.h:74
void log_smgrcreate(RelFileNode *rnode, ForkNumber forkNum)
Definition: storage.c:125
void smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:734
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 1017 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, NULL, 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().

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

Definition at line 1755 of file heap.c.

References AccessExclusiveLock, CacheInvalidateRelcache(), CatalogTupleDelete(), CheckTableForSerializableConflictIn(), CheckTableNotInUse(), DeleteAttributeTuples(), DeleteRelationTuple(), elog, ERROR, FOREIGNTABLEREL, ForeignTableRelationId, get_partition_parent(), heap_close, heap_open(), HeapTupleIsValid, InvalidOid, NoLock, NULL, ObjectIdGetDatum, RelationData::rd_rel, relation_close(), relation_open(), RelationDropStorage(), RelationForgetRelation(), RelationRemoveInheritance(), ReleaseSysCache(), RELKIND_COMPOSITE_TYPE, RELKIND_FOREIGN_TABLE, RELKIND_PARTITIONED_TABLE, RELKIND_VIEW, remove_on_commit_action(), RemovePartitionKeyByRelId(), RemoveStatistics(), RemoveStatisticsExt(), RemoveSubscriptionRel(), RowExclusiveLock, SearchSysCache1, and HeapTupleData::t_self.

Referenced by doDeletion().

1756 {
1757  Relation rel;
1758  Oid parentOid;
1759  Relation parent = NULL;
1760 
1761  /*
1762  * Open and lock the relation.
1763  */
1764  rel = relation_open(relid, AccessExclusiveLock);
1765 
1766  /*
1767  * If the relation is a partition, we must grab exclusive lock on its
1768  * parent because we need to update its partition descriptor. We must take
1769  * a table lock strong enough to prevent all queries on the parent from
1770  * proceeding until we commit and send out a shared-cache-inval notice
1771  * that will make them update their partition descriptor. Sometimes, doing
1772  * this is cycles spent uselessly, especially if the parent will be
1773  * dropped as part of the same command anyway.
1774  */
1775  if (rel->rd_rel->relispartition)
1776  {
1777  parentOid = get_partition_parent(relid);
1778  parent = heap_open(parentOid, AccessExclusiveLock);
1779  }
1780 
1781  /*
1782  * There can no longer be anyone *else* touching the relation, but we
1783  * might still have open queries or cursors, or pending trigger events, in
1784  * our own session.
1785  */
1786  CheckTableNotInUse(rel, "DROP TABLE");
1787 
1788  /*
1789  * This effectively deletes all rows in the table, and may be done in a
1790  * serializable transaction. In that case we must record a rw-conflict in
1791  * to this transaction from each transaction holding a predicate lock on
1792  * the table.
1793  */
1795 
1796  /*
1797  * Delete pg_foreign_table tuple first.
1798  */
1799  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1800  {
1801  Relation rel;
1802  HeapTuple tuple;
1803 
1805 
1807  if (!HeapTupleIsValid(tuple))
1808  elog(ERROR, "cache lookup failed for foreign table %u", relid);
1809 
1810  CatalogTupleDelete(rel, &tuple->t_self);
1811 
1812  ReleaseSysCache(tuple);
1814  }
1815 
1816  /*
1817  * If a partitioned table, delete the pg_partitioned_table tuple.
1818  */
1819  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1821 
1822  /*
1823  * Schedule unlinking of the relation's physical files at commit.
1824  */
1825  if (rel->rd_rel->relkind != RELKIND_VIEW &&
1826  rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
1827  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
1828  {
1829  RelationDropStorage(rel);
1830  }
1831 
1832  /*
1833  * Close relcache entry, but *keep* AccessExclusiveLock on the relation
1834  * until transaction commit. This ensures no one else will try to do
1835  * something with the doomed relation.
1836  */
1837  relation_close(rel, NoLock);
1838 
1839  /*
1840  * Remove any associated relation synchronization states.
1841  */
1843 
1844  /*
1845  * Forget any ON COMMIT action for the rel
1846  */
1847  remove_on_commit_action(relid);
1848 
1849  /*
1850  * Flush the relation from the relcache. We want to do this before
1851  * starting to remove catalog entries, just to be certain that no relcache
1852  * entry rebuild will happen partway through. (That should not really
1853  * matter, since we don't do CommandCounterIncrement here, but let's be
1854  * safe.)
1855  */
1856  RelationForgetRelation(relid);
1857 
1858  /*
1859  * remove inheritance information
1860  */
1862 
1863  /*
1864  * delete statistics
1865  */
1866  RemoveStatistics(relid, 0);
1867  RemoveStatisticsExt(relid, 0);
1868 
1869  /*
1870  * delete attribute tuples
1871  */
1872  DeleteAttributeTuples(relid);
1873 
1874  /*
1875  * delete relation tuple
1876  */
1877  DeleteRelationTuple(relid);
1878 
1879  if (parent)
1880  {
1881  /*
1882  * Invalidate the parent's relcache so that the partition is no longer
1883  * included in its partition descriptor.
1884  */
1885  CacheInvalidateRelcache(parent);
1886  heap_close(parent, NoLock); /* keep the lock */
1887  }
1888 }
void RemoveSubscriptionRel(Oid subid, Oid relid)
void remove_on_commit_action(Oid relid)
Definition: tablecmds.c:12425
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1263
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2680
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
void RemoveStatisticsExt(Oid relid, AttrNumber attnum)
Definition: heap.c:2786
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Oid get_partition_parent(Oid relid)
Definition: partition.c:851
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:2970
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
void RelationDropStorage(Relation rel)
Definition: storage.c:145
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define InvalidOid
Definition: postgres_ext.h:36
void DeleteRelationTuple(Oid relid)
Definition: heap.c:1430
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
static void RelationRemoveInheritance(Oid relid)
Definition: heap.c:1397
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4327
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1459
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1225
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:2740
#define AccessExclusiveLock
Definition: lockdefs.h:46
void RemovePartitionKeyByRelId(Oid relid)
Definition: heap.c:3260
#define RELKIND_VIEW
Definition: pg_class.h:164
#define ForeignTableRelationId
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1117
#define elog
Definition: elog.h:219
void heap_truncate ( List relids)

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

2898 {
2899  List *relations = NIL;
2900  ListCell *cell;
2901 
2902  /* Open relations for processing, and grab exclusive access on each */
2903  foreach(cell, relids)
2904  {
2905  Oid rid = lfirst_oid(cell);
2906  Relation rel;
2907 
2908  rel = heap_open(rid, AccessExclusiveLock);
2909  relations = lappend(relations, rel);
2910  }
2911 
2912  /* Don't allow truncate on tables that are referenced by foreign keys */
2913  heap_truncate_check_FKs(relations, true);
2914 
2915  /* OK to do it */
2916  foreach(cell, relations)
2917  {
2918  Relation rel = lfirst(cell);
2919 
2920  /* Truncate the relation */
2921  heap_truncate_one_rel(rel);
2922 
2923  /* Close the relation, but keep exclusive lock on it until commit */
2924  heap_close(rel, NoLock);
2925  }
2926 }
#define NIL
Definition: pg_list.h:69
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:2938
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:2975
#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:1287
#define lfirst(lc)
Definition: pg_list.h:106
#define AccessExclusiveLock
Definition: lockdefs.h:46
Definition: pg_list.h:45
#define lfirst_oid(lc)
Definition: pg_list.h:108
void heap_truncate_check_FKs ( List relations,
bool  tempTables 
)

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

2976 {
2977  List *oids = NIL;
2978  List *dependents;
2979  ListCell *cell;
2980 
2981  /*
2982  * Build a list of OIDs of the interesting relations.
2983  *
2984  * If a relation has no triggers, then it can neither have FKs nor be
2985  * referenced by a FK from another table, so we can ignore it.
2986  */
2987  foreach(cell, relations)
2988  {
2989  Relation rel = lfirst(cell);
2990 
2991  if (rel->rd_rel->relhastriggers)
2992  oids = lappend_oid(oids, RelationGetRelid(rel));
2993  }
2994 
2995  /*
2996  * Fast path: if no relation has triggers, none has FKs either.
2997  */
2998  if (oids == NIL)
2999  return;
3000 
3001  /*
3002  * Otherwise, must scan pg_constraint. We make one pass with all the
3003  * relations considered; if this finds nothing, then all is well.
3004  */
3005  dependents = heap_truncate_find_FKs(oids);
3006  if (dependents == NIL)
3007  return;
3008 
3009  /*
3010  * Otherwise we repeat the scan once per relation to identify a particular
3011  * pair of relations to complain about. This is pretty slow, but
3012  * performance shouldn't matter much in a failure path. The reason for
3013  * doing things this way is to ensure that the message produced is not
3014  * dependent on chance row locations within pg_constraint.
3015  */
3016  foreach(cell, oids)
3017  {
3018  Oid relid = lfirst_oid(cell);
3019  ListCell *cell2;
3020 
3021  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
3022 
3023  foreach(cell2, dependents)
3024  {
3025  Oid relid2 = lfirst_oid(cell2);
3026 
3027  if (!list_member_oid(oids, relid2))
3028  {
3029  char *relname = get_rel_name(relid);
3030  char *relname2 = get_rel_name(relid2);
3031 
3032  if (tempTables)
3033  ereport(ERROR,
3034  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3035  errmsg("unsupported ON COMMIT and foreign key combination"),
3036  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3037  relname2, relname)));
3038  else
3039  ereport(ERROR,
3040  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3041  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3042  errdetail("Table \"%s\" references \"%s\".",
3043  relname2, relname),
3044  errhint("Truncate table \"%s\" at the same time, "
3045  "or use TRUNCATE ... CASCADE.",
3046  relname2)));
3047  }
3048  }
3049  }
3050 }
#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:145
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:1694
#define RelationGetRelid(relation)
Definition: rel.h:417
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3067
#define lfirst_oid(lc)
Definition: pg_list.h:108
List* heap_truncate_find_FKs ( List relationIds)

Definition at line 3067 of file heap.c.

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

Referenced by ExecuteTruncate(), and heap_truncate_check_FKs().

3068 {
3069  List *result = NIL;
3070  Relation fkeyRel;
3071  SysScanDesc fkeyScan;
3072  HeapTuple tuple;
3073 
3074  /*
3075  * Must scan pg_constraint. Right now, it is a seqscan because there is
3076  * no available index on confrelid.
3077  */
3079 
3080  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3081  NULL, 0, NULL);
3082 
3083  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3084  {
3086 
3087  /* Not a foreign key */
3088  if (con->contype != CONSTRAINT_FOREIGN)
3089  continue;
3090 
3091  /* Not referencing one of our list of tables */
3092  if (!list_member_oid(relationIds, con->confrelid))
3093  continue;
3094 
3095  /* Add referencer unless already in input or result list */
3096  if (!list_member_oid(relationIds, con->conrelid))
3097  result = insert_ordered_unique_oid(result, con->conrelid);
3098  }
3099 
3100  systable_endscan(fkeyScan);
3101  heap_close(fkeyRel, AccessShareLock);
3102 
3103  return result;
3104 }
#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:656
#define AccessShareLock
Definition: lockdefs.h:36
return result
Definition: formatting.c:1618
#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:1287
#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
#define NULL
Definition: c.h:229
static List * insert_ordered_unique_oid(List *list, Oid datum)
Definition: heap.c:3117
#define ConstraintRelationId
Definition: pg_constraint.h:29
Definition: pg_list.h:45
void heap_truncate_one_rel ( Relation  rel)

Definition at line 2938 of file heap.c.

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

Referenced by ExecuteTruncate(), and heap_truncate().

2939 {
2940  Oid toastrelid;
2941 
2942  /* Truncate the actual file (and discard buffers) */
2943  RelationTruncate(rel, 0);
2944 
2945  /* If the relation has indexes, truncate the indexes too */
2947 
2948  /* If there is a toast table, truncate that too */
2949  toastrelid = rel->rd_rel->reltoastrelid;
2950  if (OidIsValid(toastrelid))
2951  {
2952  Relation toastrel = heap_open(toastrelid, AccessExclusiveLock);
2953 
2954  RelationTruncate(toastrel, 0);
2955  RelationTruncateIndexes(toastrel);
2956  /* keep the lock... */
2957  heap_close(toastrel, NoLock);
2958  }
2959 }
#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:538
#define NoLock
Definition: lockdefs.h:34
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define AccessExclusiveLock
Definition: lockdefs.h:46
static void RelationTruncateIndexes(Relation heapRelation)
Definition: heap.c:2856
void RelationTruncate(Relation rel, BlockNumber nblocks)
Definition: storage.c:227
void InsertPgAttributeTuple ( Relation  pg_attribute_rel,
Form_pg_attribute  new_attribute,
CatalogIndexState  indstate 
)

Definition at line 597 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_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, NULL, ObjectIdGetDatum, RelationGetDescr, and values.

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

600 {
602  bool nulls[Natts_pg_attribute];
603  HeapTuple tup;
604 
605  /* This is a tad tedious, but way cleaner than what we used to do... */
606  memset(values, 0, sizeof(values));
607  memset(nulls, false, sizeof(nulls));
608 
609  values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
610  values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
611  values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
612  values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
613  values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
614  values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
615  values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
616  values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(new_attribute->attcacheoff);
617  values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
618  values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
619  values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
620  values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
621  values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
622  values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
623  values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
624  values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
625  values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
626  values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
627 
628  /* start out with empty permissions and empty options */
629  nulls[Anum_pg_attribute_attacl - 1] = true;
630  nulls[Anum_pg_attribute_attoptions - 1] = true;
631  nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
632 
633  tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
634 
635  /* finally insert the new tuple, update the indexes, and clean up */
636  if (indstate != NULL)
637  CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
638  else
639  CatalogTupleInsert(pg_attribute_rel, tup);
640 
641  heap_freetuple(tup);
642 }
#define Anum_pg_attribute_attrelid
Definition: pg_attribute.h:192
#define Anum_pg_attribute_attinhcount
Definition: pg_attribute.h:208
#define Anum_pg_attribute_atttypid
Definition: pg_attribute.h:194
#define Anum_pg_attribute_attlen
Definition: pg_attribute.h:196
#define NameGetDatum(X)
Definition: postgres.h:601
#define Anum_pg_attribute_attbyval
Definition: pg_attribute.h:201
#define Anum_pg_attribute_attnum
Definition: pg_attribute.h:197
#define RelationGetDescr(relation)
Definition: rel.h:429
#define Anum_pg_attribute_atthasdef
Definition: pg_attribute.h:205
#define Int16GetDatum(X)
Definition: postgres.h:457
#define Anum_pg_attribute_attndims
Definition: pg_attribute.h:198
#define Anum_pg_attribute_attacl
Definition: pg_attribute.h:210
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
#define Anum_pg_attribute_attislocal
Definition: pg_attribute.h:207
#define Anum_pg_attribute_attisdropped
Definition: pg_attribute.h:206
#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:195
#define Anum_pg_attribute_atttypmod
Definition: pg_attribute.h:200
#define Anum_pg_attribute_attcacheoff
Definition: pg_attribute.h:199
uintptr_t Datum
Definition: postgres.h:372
#define Anum_pg_attribute_attalign
Definition: pg_attribute.h:203
#define BoolGetDatum(X)
Definition: postgres.h:408
#define NULL
Definition: c.h:229
#define Anum_pg_attribute_attnotnull
Definition: pg_attribute.h:204
#define Anum_pg_attribute_attfdwoptions
Definition: pg_attribute.h:212
#define CharGetDatum(X)
Definition: postgres.h:422
static Datum values[MAXATTR]
Definition: bootstrap.c:162
#define Int32GetDatum(X)
Definition: postgres.h:485
#define Anum_pg_attribute_attoptions
Definition: pg_attribute.h:211
#define Natts_pg_attribute
Definition: pg_attribute.h:191
#define Anum_pg_attribute_attcollation
Definition: pg_attribute.h:209
Oid CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:186
#define Anum_pg_attribute_attstorage
Definition: pg_attribute.h:202
#define Anum_pg_attribute_attname
Definition: pg_attribute.h:193
void InsertPgClassTuple ( Relation  pg_class_desc,
Relation  new_rel_desc,
Oid  new_rel_oid,
Datum  relacl,
Datum  reloptions 
)

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

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

Definition at line 1628 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, NULL, ObjectAddressStack::object, ObjectIdGetDatum, PERFORM_DELETION_INTERNAL, performDeletion(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by ATExecAlterColumnType(), and ATExecColumnDefault().

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

Definition at line 1682 of file heap.c.

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

Referenced by doDeletion().

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

Definition at line 1537 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(), RemoveStatisticsExt(), RowExclusiveLock, SearchSysCacheCopy2, snprintf(), and HeapTupleData::t_self.

Referenced by doDeletion().

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

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

3261 {
3262  Relation rel;
3263  HeapTuple tuple;
3264 
3266 
3267  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3268  if (!HeapTupleIsValid(tuple))
3269  elog(ERROR, "cache lookup failed for partition key of relation %u",
3270  relid);
3271 
3272  CatalogTupleDelete(rel, &tuple->t_self);
3273 
3274  ReleaseSysCache(tuple);
3276 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#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
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define elog
Definition: elog.h:219
void RemoveStatistics ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 2740 of file heap.c.

References Anum_pg_statistic_staattnum, Anum_pg_statistic_starelid, BTEqualStrategyNumber, CatalogTupleDelete(), heap_close, heap_open(), HeapTupleIsValid, Int16GetDatum, NULL, 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().

2741 {
2742  Relation pgstatistic;
2743  SysScanDesc scan;
2744  ScanKeyData key[2];
2745  int nkeys;
2746  HeapTuple tuple;
2747 
2749 
2750  ScanKeyInit(&key[0],
2752  BTEqualStrategyNumber, F_OIDEQ,
2753  ObjectIdGetDatum(relid));
2754 
2755  if (attnum == 0)
2756  nkeys = 1;
2757  else
2758  {
2759  ScanKeyInit(&key[1],
2761  BTEqualStrategyNumber, F_INT2EQ,
2762  Int16GetDatum(attnum));
2763  nkeys = 2;
2764  }
2765 
2766  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
2767  NULL, nkeys, key);
2768 
2769  /* we must loop even when attnum != 0, in case of inherited stats */
2770  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
2771  CatalogTupleDelete(pgstatistic, &tuple->t_self);
2772 
2773  systable_endscan(scan);
2774 
2775  heap_close(pgstatistic, RowExclusiveLock);
2776 }
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:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#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
void RemoveStatisticsExt ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 2786 of file heap.c.

References Anum_pg_statistic_ext_starelid, BTEqualStrategyNumber, CatalogTupleDelete(), deleteDependencyRecordsFor(), GETSTRUCT, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, i, NULL, ObjectIdGetDatum, RowExclusiveLock, ScanKeyInit(), StatisticExtRelationId, StatisticExtRelidIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), and HeapTupleData::t_self.

Referenced by heap_drop_with_catalog(), and RemoveAttributeById().

2787 {
2788  Relation pgstatisticext;
2789  SysScanDesc scan;
2790  ScanKeyData key;
2791  HeapTuple tuple;
2792 
2793  /*
2794  * Scan pg_statistic_ext to delete relevant tuples
2795  */
2797 
2798  ScanKeyInit(&key,
2800  BTEqualStrategyNumber, F_OIDEQ,
2801  ObjectIdGetDatum(relid));
2802 
2803  scan = systable_beginscan(pgstatisticext,
2805  true, NULL, 1, &key);
2806 
2807  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
2808  {
2809  bool delete = false;
2810 
2811  if (attnum == 0)
2812  delete = true;
2813  else if (attnum != 0)
2814  {
2815  Form_pg_statistic_ext staForm;
2816  int i;
2817 
2818  /*
2819  * Decode the stakeys array and delete any stats that involve the
2820  * specified column.
2821  */
2822  staForm = (Form_pg_statistic_ext) GETSTRUCT(tuple);
2823  for (i = 0; i < staForm->stakeys.dim1; i++)
2824  {
2825  if (staForm->stakeys.values[i] == attnum)
2826  {
2827  delete = true;
2828  break;
2829  }
2830  }
2831  }
2832 
2833  if (delete)
2834  {
2835  CatalogTupleDelete(pgstatisticext, &tuple->t_self);
2837  HeapTupleGetOid(tuple),
2838  false);
2839  }
2840  }
2841 
2842  systable_endscan(scan);
2843 
2844  heap_close(pgstatisticext, RowExclusiveLock);
2845 }
#define Anum_pg_statistic_ext_starelid
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:191
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define heap_close(r, l)
Definition: heapam.h:97
#define StatisticExtRelidIndexId
Definition: indexing.h:190
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:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define StatisticExtRelationId
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
#define BTEqualStrategyNumber
Definition: stratnum.h:31
FormData_pg_statistic_ext * Form_pg_statistic_ext
Oid StoreAttrDefault ( Relation  rel,
AttrNumber  attnum,
Node expr,
bool  is_internal 
)

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

1899 {
1900  char *adbin;
1901  char *adsrc;
1902  Relation adrel;
1903  HeapTuple tuple;
1904  Datum values[4];
1905  static bool nulls[4] = {false, false, false, false};
1906  Relation attrrel;
1907  HeapTuple atttup;
1908  Form_pg_attribute attStruct;
1909  Oid attrdefOid;
1910  ObjectAddress colobject,
1911  defobject;
1912 
1913  /*
1914  * Flatten expression to string form for storage.
1915  */
1916  adbin = nodeToString(expr);
1917 
1918  /*
1919  * Also deparse it to form the mostly-obsolete adsrc field.
1920  */
1921  adsrc = deparse_expression(expr,
1923  RelationGetRelid(rel)),
1924  false, false);
1925 
1926  /*
1927  * Make the pg_attrdef entry.
1928  */
1929  values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
1930  values[Anum_pg_attrdef_adnum - 1] = attnum;
1931  values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
1932  values[Anum_pg_attrdef_adsrc - 1] = CStringGetTextDatum(adsrc);
1933 
1935 
1936  tuple = heap_form_tuple(adrel->rd_att, values, nulls);
1937  attrdefOid = CatalogTupleInsert(adrel, tuple);
1938 
1939  defobject.classId = AttrDefaultRelationId;
1940  defobject.objectId = attrdefOid;
1941  defobject.objectSubId = 0;
1942 
1943  heap_close(adrel, RowExclusiveLock);
1944 
1945  /* now can free some of the stuff allocated above */
1948  heap_freetuple(tuple);
1949  pfree(adbin);
1950  pfree(adsrc);
1951 
1952  /*
1953  * Update the pg_attribute entry for the column to show that a default
1954  * exists.
1955  */
1957  atttup = SearchSysCacheCopy2(ATTNUM,
1959  Int16GetDatum(attnum));
1960  if (!HeapTupleIsValid(atttup))
1961  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1962  attnum, RelationGetRelid(rel));
1963  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
1964  if (!attStruct->atthasdef)
1965  {
1966  attStruct->atthasdef = true;
1967  CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
1968  }
1969  heap_close(attrrel, RowExclusiveLock);
1970  heap_freetuple(atttup);
1971 
1972  /*
1973  * Make a dependency so that the pg_attrdef entry goes away if the column
1974  * (or whole table) is deleted.
1975  */
1976  colobject.classId = RelationRelationId;
1977  colobject.objectId = RelationGetRelid(rel);
1978  colobject.objectSubId = attnum;
1979 
1980  recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
1981 
1982  /*
1983  * Record dependencies on objects used in the expression, too.
1984  */
1985  recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
1986 
1987  /*
1988  * Post creation hook for attribute defaults.
1989  *
1990  * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
1991  * couple of deletion/creation of the attribute's default entry, so the
1992  * callee should check existence of an older version of this entry if it
1993  * needs to distinguish.
1994  */
1996  RelationGetRelid(rel), attnum, is_internal);
1997 
1998  return attrdefOid;
1999 }
#define NIL
Definition: pg_list.h:69
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#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:692
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
void pfree(void *pointer)
Definition: mcxt.c:950
#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:2956
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1338
#define RelationGetRelationName(relation)
Definition: rel.h:437
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:184
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:1287
#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:2897
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:162
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4154
#define elog
Definition: elog.h:219
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:163
#define AttrDefaultRelationId
Definition: pg_attrdef.h:29
#define RelationGetRelid(relation)
Definition: rel.h:417
void StorePartitionBound ( Relation  rel,
Relation  parent,
Node bound 
)

Definition at line 3287 of file heap.c.

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

Referenced by ATExecAttachPartition(), and DefineRelation().

3288 {
3289  Relation classRel;
3290  HeapTuple tuple,
3291  newtuple;
3292  Datum new_val[Natts_pg_class];
3293  bool new_null[Natts_pg_class],
3294  new_repl[Natts_pg_class];
3295 
3296  /* Update pg_class tuple */
3298  tuple = SearchSysCacheCopy1(RELOID,
3300  if (!HeapTupleIsValid(tuple))
3301  elog(ERROR, "cache lookup failed for relation %u",
3302  RelationGetRelid(rel));
3303 
3304 #ifdef USE_ASSERT_CHECKING
3305  {
3306  Form_pg_class classForm;
3307  bool isnull;
3308 
3309  classForm = (Form_pg_class) GETSTRUCT(tuple);
3310  Assert(!classForm->relispartition);
3312  &isnull);
3313  Assert(isnull);
3314  }
3315 #endif
3316 
3317  /* Fill in relpartbound value */
3318  memset(new_val, 0, sizeof(new_val));
3319  memset(new_null, false, sizeof(new_null));
3320  memset(new_repl, false, sizeof(new_repl));
3322  new_null[Anum_pg_class_relpartbound - 1] = false;
3323  new_repl[Anum_pg_class_relpartbound - 1] = true;
3324  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3325  new_val, new_null, new_repl);
3326  /* Also set the flag */
3327  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3328  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3329  heap_freetuple(newtuple);
3330  heap_close(classRel, RowExclusiveLock);
3331 
3332  CacheInvalidateRelcache(parent);
3333 }
#define Natts_pg_class
Definition: pg_class.h:102
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationGetDescr(relation)
Definition: rel.h:429
#define RelationRelationId
Definition: pg_class.h:29
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
#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
uintptr_t Datum
Definition: postgres.h:372
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define Anum_pg_class_relpartbound
Definition: pg_class.h:135
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:675
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1225
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:161
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4154
#define elog
Definition: elog.h:219
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:793
#define RelationGetRelid(relation)
Definition: rel.h:417
void StorePartitionKey ( Relation  rel,
char  strategy,
int16  partnatts,
AttrNumber partattrs,
List partexprs,
Oid partopclass,
Oid partcollation 
)

Definition at line 3151 of file heap.c.

References Anum_pg_partitioned_table_partattrs, Anum_pg_partitioned_table_partclass, Anum_pg_partitioned_table_partcollation, 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, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, heap_close, heap_form_tuple(), heap_open(), i, Int16GetDatum, MemSet, Natts_pg_partitioned_table, nodeToString(), ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OperatorClassRelationId, PartitionedRelationId, PARTRELID, pfree(), PointerGetDatum, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetDescr, RelationGetRelid, RelationRelationId, RELKIND_PARTITIONED_TABLE, RowExclusiveLock, SearchSysCache1, and values.

Referenced by DefineRelation().

3158 {
3159  int i;
3160  int2vector *partattrs_vec;
3161  oidvector *partopclass_vec;
3162  oidvector *partcollation_vec;
3163  Datum partexprDatum;
3164  Relation pg_partitioned_table;
3165  HeapTuple tuple;
3167  bool nulls[Natts_pg_partitioned_table];
3168  ObjectAddress myself;
3169  ObjectAddress referenced;
3170 
3171  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3172 
3173  tuple = SearchSysCache1(PARTRELID,
3175 
3176  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3177  partattrs_vec = buildint2vector(partattrs, partnatts);
3178  partopclass_vec = buildoidvector(partopclass, partnatts);
3179  partcollation_vec = buildoidvector(partcollation, partnatts);
3180 
3181  /* Convert the expressions (if any) to a text datum */
3182  if (partexprs)
3183  {
3184  char *exprString;
3185 
3186  exprString = nodeToString(partexprs);
3187  partexprDatum = CStringGetTextDatum(exprString);
3188  pfree(exprString);
3189  }
3190  else
3191  partexprDatum = (Datum) 0;
3192 
3193  pg_partitioned_table = heap_open(PartitionedRelationId, RowExclusiveLock);
3194 
3195  MemSet(nulls, false, sizeof(nulls));
3196 
3197  /* Only this can ever be NULL */
3198  if (!partexprDatum)
3199  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3200 
3202  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3203  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3204  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3205  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3206  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3207  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3208 
3209  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3210 
3211  CatalogTupleInsert(pg_partitioned_table, tuple);
3212  heap_close(pg_partitioned_table, RowExclusiveLock);
3213 
3214  /* Mark this relation as dependent on a few things as follows */
3215  myself.classId = RelationRelationId;
3216  myself.objectId = RelationGetRelid(rel);;
3217  myself.objectSubId = 0;
3218 
3219  /* Operator class and collation per key column */
3220  for (i = 0; i < partnatts; i++)
3221  {
3222  referenced.classId = OperatorClassRelationId;
3223  referenced.objectId = partopclass[i];
3224  referenced.objectSubId = 0;
3225 
3226  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3227 
3228  referenced.classId = CollationRelationId;
3229  referenced.objectId = partcollation[i];
3230  referenced.objectSubId = 0;
3231 
3232  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3233  }
3234 
3235  /*
3236  * Anything mentioned in the expressions. We must ignore the column
3237  * references, which will depend on the table itself; there is no separate
3238  * partition key object.
3239  */
3240  if (partexprs)
3242  (Node *) partexprs,
3243  RelationGetRelid(rel),
3245  DEPENDENCY_AUTO, true);
3246 
3247  /*
3248  * We must invalidate the relcache so that the next
3249  * CommandCounterIncrement() will cause the same to be rebuilt using the
3250  * information in just created catalog entry.
3251  */
3253 }
Definition: c.h:478
#define RelationGetDescr(relation)
Definition: rel.h:429
#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:522
#define MemSet(start, val, len)
Definition: c.h:857
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:692
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define Anum_pg_partitioned_table_partrelid
void pfree(void *pointer)
Definition: mcxt.c:950
#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 RowExclusiveLock
Definition: lockdefs.h:38
#define Anum_pg_partitioned_table_partnatts
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
Definition: c.h:467
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define CollationRelationId
Definition: pg_collation.h:30
#define Anum_pg_partitioned_table_partstrat
#define Assert(condition)
Definition: c.h:675
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:1379
#define CharGetDatum(X)
Definition: postgres.h:422
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1225
static Datum values[MAXATTR]
Definition: bootstrap.c:162
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4154
#define Anum_pg_partitioned_table_partclass
#define Anum_pg_partitioned_table_partattrs
#define RelationGetRelid(relation)
Definition: rel.h:417
Form_pg_attribute SystemAttributeByName ( const char *  attname,
bool  relhasoids 
)

Definition at line 214 of file heap.c.

References lengthof, NameStr, NULL, and ObjectIdAttributeNumber.

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:562
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:184
#define NULL
Definition: c.h:229
#define NameStr(name)
Definition: c.h:499
Form_pg_attribute SystemAttributeDefinition ( AttrNumber  attno,
bool  relhasoids 
)

Definition at line 200 of file heap.c.

References elog, ERROR, lengthof, and ObjectIdAttributeNumber.

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