PostgreSQL Source Code  git master
heap.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * heap.c
4  * code to create and destroy POSTGRES heap relations
5  *
6  * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/catalog/heap.c
12  *
13  *
14  * INTERFACE ROUTINES
15  * heap_create() - Create an uncataloged heap relation
16  * heap_create_with_catalog() - Create a cataloged relation
17  * heap_drop_with_catalog() - Removes named relation from catalogs
18  *
19  * NOTES
20  * this code taken from access/heap/create.c, which contains
21  * the old heap_create_with_catalog, amcreate, and amdestroy.
22  * those routines will soon call these routines using the function
23  * manager,
24  * just like the poorly named "NewXXX" routines do. The
25  * "New" routines are all going to die soon, once and for all!
26  * -cim 1/13/91
27  *
28  *-------------------------------------------------------------------------
29  */
30 #include "postgres.h"
31 
32 #include "access/htup_details.h"
33 #include "access/multixact.h"
34 #include "access/sysattr.h"
35 #include "access/transam.h"
36 #include "access/xact.h"
37 #include "access/xlog.h"
38 #include "catalog/binary_upgrade.h"
39 #include "catalog/catalog.h"
40 #include "catalog/dependency.h"
41 #include "catalog/heap.h"
42 #include "catalog/index.h"
43 #include "catalog/objectaccess.h"
44 #include "catalog/partition.h"
45 #include "catalog/pg_attrdef.h"
46 #include "catalog/pg_collation.h"
47 #include "catalog/pg_constraint.h"
50 #include "catalog/pg_inherits.h"
51 #include "catalog/pg_namespace.h"
52 #include "catalog/pg_opclass.h"
54 #include "catalog/pg_statistic.h"
56 #include "catalog/pg_tablespace.h"
57 #include "catalog/pg_type.h"
58 #include "catalog/pg_type_fn.h"
59 #include "catalog/storage.h"
60 #include "catalog/storage_xlog.h"
61 #include "commands/tablecmds.h"
62 #include "commands/typecmds.h"
63 #include "miscadmin.h"
64 #include "nodes/nodeFuncs.h"
65 #include "optimizer/var.h"
66 #include "parser/parse_coerce.h"
67 #include "parser/parse_collate.h"
68 #include "parser/parse_expr.h"
69 #include "parser/parse_relation.h"
70 #include "storage/lmgr.h"
71 #include "storage/predicate.h"
72 #include "storage/smgr.h"
73 #include "utils/acl.h"
74 #include "utils/builtins.h"
75 #include "utils/fmgroids.h"
76 #include "utils/inval.h"
77 #include "utils/lsyscache.h"
78 #include "utils/rel.h"
79 #include "utils/ruleutils.h"
80 #include "utils/snapmgr.h"
81 #include "utils/syscache.h"
82 #include "utils/tqual.h"
83 
84 
85 /* Potentially set by pg_upgrade_support functions */
88 
89 static void AddNewRelationTuple(Relation pg_class_desc,
90  Relation new_rel_desc,
91  Oid new_rel_oid,
92  Oid new_type_oid,
93  Oid reloftype,
94  Oid relowner,
95  char relkind,
96  Datum relacl,
97  Datum reloptions);
98 static ObjectAddress AddNewRelationType(const char *typeName,
99  Oid typeNamespace,
100  Oid new_rel_oid,
101  char new_rel_kind,
102  Oid ownerid,
103  Oid new_row_type,
104  Oid new_array_type);
105 static void RelationRemoveInheritance(Oid relid);
106 static Oid StoreRelCheck(Relation rel, const char *ccname, Node *expr,
107  bool is_validated, bool is_local, int inhcount,
108  bool is_no_inherit, bool is_internal);
109 static void StoreConstraints(Relation rel, List *cooked_constraints,
110  bool is_internal);
111 static bool MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
112  bool allow_merge, bool is_local,
113  bool is_initially_valid,
114  bool is_no_inherit);
115 static void SetRelationNumChecks(Relation rel, int numchecks);
116 static Node *cookConstraint(ParseState *pstate,
117  Node *raw_constraint,
118  char *relname);
119 static List *insert_ordered_unique_oid(List *list, Oid datum);
120 
121 
122 /* ----------------------------------------------------------------
123  * XXX UGLY HARD CODED BADNESS FOLLOWS XXX
124  *
125  * these should all be moved to someplace in the lib/catalog
126  * module, if not obliterated first.
127  * ----------------------------------------------------------------
128  */
129 
130 
131 /*
132  * Note:
133  * Should the system special case these attributes in the future?
134  * Advantage: consume much less space in the ATTRIBUTE relation.
135  * Disadvantage: special cases will be all over the place.
136  */
137 
138 /*
139  * The initializers below do not include trailing variable length fields,
140  * but that's OK - we're never going to reference anything beyond the
141  * fixed-size portion of the structure anyway.
142  */
143 
145  0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
147  false, 'p', 's', true, false, '\0', false, true, 0
148 };
149 
151  0, {"oid"}, OIDOID, 0, sizeof(Oid),
152  ObjectIdAttributeNumber, 0, -1, -1,
153  true, 'p', 'i', true, false, '\0', false, true, 0
154 };
155 
157  0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
159  true, 'p', 'i', true, false, '\0', false, true, 0
160 };
161 
163  0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
164  MinCommandIdAttributeNumber, 0, -1, -1,
165  true, 'p', 'i', true, false, '\0', false, true, 0
166 };
167 
169  0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
171  true, 'p', 'i', true, false, '\0', false, true, 0
172 };
173 
175  0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
176  MaxCommandIdAttributeNumber, 0, -1, -1,
177  true, 'p', 'i', true, false, '\0', false, true, 0
178 };
179 
180 /*
181  * We decided to call this attribute "tableoid" rather than say
182  * "classoid" on the basis that in the future there may be more than one
183  * table of a particular class/type. In any case table is still the word
184  * used in SQL.
185  */
187  0, {"tableoid"}, OIDOID, 0, sizeof(Oid),
188  TableOidAttributeNumber, 0, -1, -1,
189  true, 'p', 'i', true, false, '\0', false, true, 0
190 };
191 
192 static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
193 
194 /*
195  * This function returns a Form_pg_attribute pointer for a system attribute.
196  * Note that we elog if the presented attno is invalid, which would only
197  * happen if there's a problem upstream.
198  */
200 SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
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 }
208 
209 /*
210  * If the given name is a system attribute name, return a Form_pg_attribute
211  * pointer for a prototype definition. If not, return NULL.
212  */
214 SystemAttributeByName(const char *attname, bool relhasoids)
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 }
231 
232 
233 /* ----------------------------------------------------------------
234  * XXX END OF UGLY HARD CODED BADNESS XXX
235  * ---------------------------------------------------------------- */
236 
237 
238 /* ----------------------------------------------------------------
239  * heap_create - Create an uncataloged heap relation
240  *
241  * Note API change: the caller must now always provide the OID
242  * to use for the relation. The relfilenode may (and, normally,
243  * should) be left unspecified.
244  *
245  * rel->rd_rel is initialized by RelationBuildLocalRelation,
246  * and is mostly zeroes at return.
247  * ----------------------------------------------------------------
248  */
249 Relation
250 heap_create(const char *relname,
251  Oid relnamespace,
252  Oid reltablespace,
253  Oid relid,
254  Oid relfilenode,
255  TupleDesc tupDesc,
256  char relkind,
257  char relpersistence,
258  bool shared_relation,
259  bool mapped_relation,
260  bool allow_system_table_mods)
261 {
262  bool create_storage;
263  Relation rel;
264 
265  /* The caller must have provided an OID for the relation. */
266  Assert(OidIsValid(relid));
267 
268  /*
269  * Don't allow creating relations in pg_catalog directly, even though it
270  * is allowed to move user defined relations there. Semantics with search
271  * paths including pg_catalog are too confusing for now.
272  *
273  * But allow creating indexes on relations in pg_catalog even if
274  * allow_system_table_mods = off, upper layers already guarantee it's on a
275  * user defined relation, not a system one.
276  */
277  if (!allow_system_table_mods &&
278  ((IsSystemNamespace(relnamespace) && relkind != RELKIND_INDEX) ||
279  IsToastNamespace(relnamespace)) &&
281  ereport(ERROR,
282  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
283  errmsg("permission denied to create \"%s.%s\"",
284  get_namespace_name(relnamespace), relname),
285  errdetail("System catalog modifications are currently disallowed.")));
286 
287  /*
288  * Decide if we need storage or not, and handle a couple other special
289  * cases for particular relkinds.
290  */
291  switch (relkind)
292  {
293  case RELKIND_VIEW:
298  create_storage = false;
299 
300  /*
301  * Force reltablespace to zero if the relation has no physical
302  * storage. This is mainly just for cleanliness' sake.
303  */
304  reltablespace = InvalidOid;
305  break;
306  case RELKIND_SEQUENCE:
307  create_storage = true;
308 
309  /*
310  * Force reltablespace to zero for sequences, since we don't
311  * support moving them around into different tablespaces.
312  */
313  reltablespace = InvalidOid;
314  break;
315  default:
316  create_storage = true;
317  break;
318  }
319 
320  /*
321  * Unless otherwise requested, the physical ID (relfilenode) is initially
322  * the same as the logical ID (OID). When the caller did specify a
323  * relfilenode, it already exists; do not attempt to create it.
324  */
325  if (OidIsValid(relfilenode))
326  create_storage = false;
327  else
328  relfilenode = relid;
329 
330  /*
331  * Never allow a pg_class entry to explicitly specify the database's
332  * default tablespace in reltablespace; force it to zero instead. This
333  * ensures that if the database is cloned with a different default
334  * tablespace, the pg_class entry will still match where CREATE DATABASE
335  * will put the physically copied relation.
336  *
337  * Yes, this is a bit of a hack.
338  */
339  if (reltablespace == MyDatabaseTableSpace)
340  reltablespace = InvalidOid;
341 
342  /*
343  * build the relcache entry.
344  */
345  rel = RelationBuildLocalRelation(relname,
346  relnamespace,
347  tupDesc,
348  relid,
349  relfilenode,
350  reltablespace,
351  shared_relation,
352  mapped_relation,
353  relpersistence,
354  relkind);
355 
356  /*
357  * Have the storage manager create the relation's disk file, if needed.
358  *
359  * We only create the main fork here, other forks will be created on
360  * demand.
361  */
362  if (create_storage)
363  {
364  RelationOpenSmgr(rel);
365  RelationCreateStorage(rel->rd_node, relpersistence);
366  }
367 
368  return rel;
369 }
370 
371 /* ----------------------------------------------------------------
372  * heap_create_with_catalog - Create a cataloged relation
373  *
374  * this is done in multiple steps:
375  *
376  * 1) CheckAttributeNamesTypes() is used to make certain the tuple
377  * descriptor contains a valid set of attribute names and types
378  *
379  * 2) pg_class is opened and get_relname_relid()
380  * performs a scan to ensure that no relation with the
381  * same name already exists.
382  *
383  * 3) heap_create() is called to create the new relation on disk.
384  *
385  * 4) TypeCreate() is called to define a new type corresponding
386  * to the new relation.
387  *
388  * 5) AddNewRelationTuple() is called to register the
389  * relation in pg_class.
390  *
391  * 6) AddNewAttributeTuples() is called to register the
392  * new relation's schema in pg_attribute.
393  *
394  * 7) StoreConstraints is called () - vadim 08/22/97
395  *
396  * 8) the relations are closed and the new relation's oid
397  * is returned.
398  *
399  * ----------------------------------------------------------------
400  */
401 
402 /* --------------------------------
403  * CheckAttributeNamesTypes
404  *
405  * this is used to make certain the tuple descriptor contains a
406  * valid set of attribute names and datatypes. a problem simply
407  * generates ereport(ERROR) which aborts the current transaction.
408  * --------------------------------
409  */
410 void
411 CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
412  bool allow_system_table_mods)
413 {
414  int i;
415  int j;
416  int natts = tupdesc->natts;
417 
418  /* Sanity check on column count */
419  if (natts < 0 || natts > MaxHeapAttributeNumber)
420  ereport(ERROR,
421  (errcode(ERRCODE_TOO_MANY_COLUMNS),
422  errmsg("tables can have at most %d columns",
423  MaxHeapAttributeNumber)));
424 
425  /*
426  * first check for collision with system attribute names
427  *
428  * Skip this for a view or type relation, since those don't have system
429  * attributes.
430  */
431  if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
432  {
433  for (i = 0; i < natts; i++)
434  {
435  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
436 
437  if (SystemAttributeByName(NameStr(attr->attname),
438  tupdesc->tdhasoid) != NULL)
439  ereport(ERROR,
440  (errcode(ERRCODE_DUPLICATE_COLUMN),
441  errmsg("column name \"%s\" conflicts with a system column name",
442  NameStr(attr->attname))));
443  }
444  }
445 
446  /*
447  * next check for repeated attribute names
448  */
449  for (i = 1; i < natts; i++)
450  {
451  for (j = 0; j < i; j++)
452  {
453  if (strcmp(NameStr(TupleDescAttr(tupdesc, j)->attname),
454  NameStr(TupleDescAttr(tupdesc, i)->attname)) == 0)
455  ereport(ERROR,
456  (errcode(ERRCODE_DUPLICATE_COLUMN),
457  errmsg("column name \"%s\" specified more than once",
458  NameStr(TupleDescAttr(tupdesc, j)->attname))));
459  }
460  }
461 
462  /*
463  * next check the attribute types
464  */
465  for (i = 0; i < natts; i++)
466  {
467  CheckAttributeType(NameStr(TupleDescAttr(tupdesc, i)->attname),
468  TupleDescAttr(tupdesc, i)->atttypid,
469  TupleDescAttr(tupdesc, i)->attcollation,
470  NIL, /* assume we're creating a new rowtype */
471  allow_system_table_mods);
472  }
473 }
474 
475 /* --------------------------------
476  * CheckAttributeType
477  *
478  * Verify that the proposed datatype of an attribute is legal.
479  * This is needed mainly because there are types (and pseudo-types)
480  * in the catalogs that we do not support as elements of real tuples.
481  * We also check some other properties required of a table column.
482  *
483  * If the attribute is being proposed for addition to an existing table or
484  * composite type, pass a one-element list of the rowtype OID as
485  * containing_rowtypes. When checking a to-be-created rowtype, it's
486  * sufficient to pass NIL, because there could not be any recursive reference
487  * to a not-yet-existing rowtype.
488  * --------------------------------
489  */
490 void
491 CheckAttributeType(const char *attname,
492  Oid atttypid, Oid attcollation,
493  List *containing_rowtypes,
494  bool allow_system_table_mods)
495 {
496  char att_typtype = get_typtype(atttypid);
497  Oid att_typelem;
498 
499  if (att_typtype == TYPTYPE_PSEUDO)
500  {
501  /*
502  * Refuse any attempt to create a pseudo-type column, except for a
503  * special hack for pg_statistic: allow ANYARRAY when modifying system
504  * catalogs (this allows creating pg_statistic and cloning it during
505  * VACUUM FULL)
506  */
507  if (atttypid != ANYARRAYOID || !allow_system_table_mods)
508  ereport(ERROR,
509  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
510  errmsg("column \"%s\" has pseudo-type %s",
511  attname, format_type_be(atttypid))));
512  }
513  else if (att_typtype == TYPTYPE_DOMAIN)
514  {
515  /*
516  * If it's a domain, recurse to check its base type.
517  */
518  CheckAttributeType(attname, getBaseType(atttypid), attcollation,
519  containing_rowtypes,
520  allow_system_table_mods);
521  }
522  else if (att_typtype == TYPTYPE_COMPOSITE)
523  {
524  /*
525  * For a composite type, recurse into its attributes.
526  */
527  Relation relation;
528  TupleDesc tupdesc;
529  int i;
530 
531  /*
532  * Check for self-containment. Eventually we might be able to allow
533  * this (just return without complaint, if so) but it's not clear how
534  * many other places would require anti-recursion defenses before it
535  * would be safe to allow tables to contain their own rowtype.
536  */
537  if (list_member_oid(containing_rowtypes, atttypid))
538  ereport(ERROR,
539  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
540  errmsg("composite type %s cannot be made a member of itself",
541  format_type_be(atttypid))));
542 
543  containing_rowtypes = lcons_oid(atttypid, containing_rowtypes);
544 
545  relation = relation_open(get_typ_typrelid(atttypid), AccessShareLock);
546 
547  tupdesc = RelationGetDescr(relation);
548 
549  for (i = 0; i < tupdesc->natts; i++)
550  {
551  Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
552 
553  if (attr->attisdropped)
554  continue;
555  CheckAttributeType(NameStr(attr->attname),
556  attr->atttypid, attr->attcollation,
557  containing_rowtypes,
558  allow_system_table_mods);
559  }
560 
561  relation_close(relation, AccessShareLock);
562 
563  containing_rowtypes = list_delete_first(containing_rowtypes);
564  }
565  else if (OidIsValid((att_typelem = get_element_type(atttypid))))
566  {
567  /*
568  * Must recurse into array types, too, in case they are composite.
569  */
570  CheckAttributeType(attname, att_typelem, attcollation,
571  containing_rowtypes,
572  allow_system_table_mods);
573  }
574 
575  /*
576  * This might not be strictly invalid per SQL standard, but it is pretty
577  * useless, and it cannot be dumped, so we must disallow it.
578  */
579  if (!OidIsValid(attcollation) && type_is_collatable(atttypid))
580  ereport(ERROR,
581  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
582  errmsg("no collation was derived for column \"%s\" with collatable type %s",
583  attname, format_type_be(atttypid)),
584  errhint("Use the COLLATE clause to set the collation explicitly.")));
585 }
586 
587 /*
588  * InsertPgAttributeTuple
589  * Construct and insert a new tuple in pg_attribute.
590  *
591  * Caller has already opened and locked pg_attribute. new_attribute is the
592  * attribute to insert (but we ignore attacl and attoptions, which are always
593  * initialized to NULL).
594  *
595  * indstate is the index state for CatalogTupleInsertWithInfo. It can be
596  * passed as NULL, in which case we'll fetch the necessary info. (Don't do
597  * this when inserting multiple attributes, because it's a tad more
598  * expensive.)
599  */
600 void
602  Form_pg_attribute new_attribute,
603  CatalogIndexState indstate)
604 {
606  bool nulls[Natts_pg_attribute];
607  HeapTuple tup;
608 
609  /* This is a tad tedious, but way cleaner than what we used to do... */
610  memset(values, 0, sizeof(values));
611  memset(nulls, false, sizeof(nulls));
612 
613  values[Anum_pg_attribute_attrelid - 1] = ObjectIdGetDatum(new_attribute->attrelid);
614  values[Anum_pg_attribute_attname - 1] = NameGetDatum(&new_attribute->attname);
615  values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(new_attribute->atttypid);
616  values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(new_attribute->attstattarget);
617  values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(new_attribute->attlen);
618  values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(new_attribute->attnum);
619  values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(new_attribute->attndims);
620  values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(new_attribute->attcacheoff);
621  values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(new_attribute->atttypmod);
622  values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(new_attribute->attbyval);
623  values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(new_attribute->attstorage);
624  values[Anum_pg_attribute_attalign - 1] = CharGetDatum(new_attribute->attalign);
625  values[Anum_pg_attribute_attnotnull - 1] = BoolGetDatum(new_attribute->attnotnull);
626  values[Anum_pg_attribute_atthasdef - 1] = BoolGetDatum(new_attribute->atthasdef);
627  values[Anum_pg_attribute_attidentity - 1] = CharGetDatum(new_attribute->attidentity);
628  values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(new_attribute->attisdropped);
629  values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
630  values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
631  values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
632 
633  /* start out with empty permissions and empty options */
634  nulls[Anum_pg_attribute_attacl - 1] = true;
635  nulls[Anum_pg_attribute_attoptions - 1] = true;
636  nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
637 
638  tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
639 
640  /* finally insert the new tuple, update the indexes, and clean up */
641  if (indstate != NULL)
642  CatalogTupleInsertWithInfo(pg_attribute_rel, tup, indstate);
643  else
644  CatalogTupleInsert(pg_attribute_rel, tup);
645 
646  heap_freetuple(tup);
647 }
648 
649 /* --------------------------------
650  * AddNewAttributeTuples
651  *
652  * this registers the new relation's schema by adding
653  * tuples to pg_attribute.
654  * --------------------------------
655  */
656 static void
658  TupleDesc tupdesc,
659  char relkind,
660  bool oidislocal,
661  int oidinhcount)
662 {
663  Form_pg_attribute attr;
664  int i;
665  Relation rel;
666  CatalogIndexState indstate;
667  int natts = tupdesc->natts;
668  ObjectAddress myself,
669  referenced;
670 
671  /*
672  * open pg_attribute and its indexes.
673  */
675 
676  indstate = CatalogOpenIndexes(rel);
677 
678  /*
679  * First we add the user attributes. This is also a convenient place to
680  * add dependencies on their datatypes and collations.
681  */
682  for (i = 0; i < natts; i++)
683  {
684  attr = TupleDescAttr(tupdesc, i);
685  /* Fill in the correct relation OID */
686  attr->attrelid = new_rel_oid;
687  /* Make sure these are OK, too */
688  attr->attstattarget = -1;
689  attr->attcacheoff = -1;
690 
691  InsertPgAttributeTuple(rel, attr, indstate);
692 
693  /* Add dependency info */
694  myself.classId = RelationRelationId;
695  myself.objectId = new_rel_oid;
696  myself.objectSubId = i + 1;
697  referenced.classId = TypeRelationId;
698  referenced.objectId = attr->atttypid;
699  referenced.objectSubId = 0;
700  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
701 
702  /* The default collation is pinned, so don't bother recording it */
703  if (OidIsValid(attr->attcollation) &&
704  attr->attcollation != DEFAULT_COLLATION_OID)
705  {
706  referenced.classId = CollationRelationId;
707  referenced.objectId = attr->attcollation;
708  referenced.objectSubId = 0;
709  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
710  }
711  }
712 
713  /*
714  * Next we add the system attributes. Skip OID if rel has no OIDs. Skip
715  * all for a view or type relation. We don't bother with making datatype
716  * dependencies here, since presumably all these types are pinned.
717  */
718  if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
719  {
720  for (i = 0; i < (int) lengthof(SysAtt); i++)
721  {
722  FormData_pg_attribute attStruct;
723 
724  /* skip OID where appropriate */
725  if (!tupdesc->tdhasoid &&
726  SysAtt[i]->attnum == ObjectIdAttributeNumber)
727  continue;
728 
729  memcpy(&attStruct, (char *) SysAtt[i], sizeof(FormData_pg_attribute));
730 
731  /* Fill in the correct relation OID in the copied tuple */
732  attStruct.attrelid = new_rel_oid;
733 
734  /* Fill in correct inheritance info for the OID column */
735  if (attStruct.attnum == ObjectIdAttributeNumber)
736  {
737  attStruct.attislocal = oidislocal;
738  attStruct.attinhcount = oidinhcount;
739  }
740 
741  InsertPgAttributeTuple(rel, &attStruct, indstate);
742  }
743  }
744 
745  /*
746  * clean up
747  */
748  CatalogCloseIndexes(indstate);
749 
751 }
752 
753 /* --------------------------------
754  * InsertPgClassTuple
755  *
756  * Construct and insert a new tuple in pg_class.
757  *
758  * Caller has already opened and locked pg_class.
759  * Tuple data is taken from new_rel_desc->rd_rel, except for the
760  * variable-width fields which are not present in a cached reldesc.
761  * relacl and reloptions are passed in Datum form (to avoid having
762  * to reference the data types in heap.h). Pass (Datum) 0 to set them
763  * to NULL.
764  * --------------------------------
765  */
766 void
768  Relation new_rel_desc,
769  Oid new_rel_oid,
770  Datum relacl,
771  Datum reloptions)
772 {
773  Form_pg_class rd_rel = new_rel_desc->rd_rel;
775  bool nulls[Natts_pg_class];
776  HeapTuple tup;
777 
778  /* This is a tad tedious, but way cleaner than what we used to do... */
779  memset(values, 0, sizeof(values));
780  memset(nulls, false, sizeof(nulls));
781 
782  values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
783  values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
784  values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
785  values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype);
786  values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner);
787  values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam);
788  values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode);
789  values[Anum_pg_class_reltablespace - 1] = ObjectIdGetDatum(rd_rel->reltablespace);
790  values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
791  values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
792  values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
793  values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
794  values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
795  values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
796  values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
797  values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
798  values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
799  values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
800  values[Anum_pg_class_relhasoids - 1] = BoolGetDatum(rd_rel->relhasoids);
801  values[Anum_pg_class_relhaspkey - 1] = BoolGetDatum(rd_rel->relhaspkey);
802  values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
803  values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
804  values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
805  values[Anum_pg_class_relforcerowsecurity - 1] = BoolGetDatum(rd_rel->relforcerowsecurity);
806  values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
807  values[Anum_pg_class_relispopulated - 1] = BoolGetDatum(rd_rel->relispopulated);
808  values[Anum_pg_class_relreplident - 1] = CharGetDatum(rd_rel->relreplident);
809  values[Anum_pg_class_relispartition - 1] = BoolGetDatum(rd_rel->relispartition);
810  values[Anum_pg_class_relfrozenxid - 1] = TransactionIdGetDatum(rd_rel->relfrozenxid);
811  values[Anum_pg_class_relminmxid - 1] = MultiXactIdGetDatum(rd_rel->relminmxid);
812  if (relacl != (Datum) 0)
813  values[Anum_pg_class_relacl - 1] = relacl;
814  else
815  nulls[Anum_pg_class_relacl - 1] = true;
816  if (reloptions != (Datum) 0)
817  values[Anum_pg_class_reloptions - 1] = reloptions;
818  else
819  nulls[Anum_pg_class_reloptions - 1] = true;
820 
821  /* relpartbound is set by updating this tuple, if necessary */
822  nulls[Anum_pg_class_relpartbound - 1] = true;
823 
824  tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
825 
826  /*
827  * The new tuple must have the oid already chosen for the rel. Sure would
828  * be embarrassing to do this sort of thing in polite company.
829  */
830  HeapTupleSetOid(tup, new_rel_oid);
831 
832  /* finally insert the new tuple, update the indexes, and clean up */
833  CatalogTupleInsert(pg_class_desc, tup);
834 
835  heap_freetuple(tup);
836 }
837 
838 /* --------------------------------
839  * AddNewRelationTuple
840  *
841  * this registers the new relation in the catalogs by
842  * adding a tuple to pg_class.
843  * --------------------------------
844  */
845 static void
847  Relation new_rel_desc,
848  Oid new_rel_oid,
849  Oid new_type_oid,
850  Oid reloftype,
851  Oid relowner,
852  char relkind,
853  Datum relacl,
854  Datum reloptions)
855 {
856  Form_pg_class new_rel_reltup;
857 
858  /*
859  * first we update some of the information in our uncataloged relation's
860  * relation descriptor.
861  */
862  new_rel_reltup = new_rel_desc->rd_rel;
863 
864  switch (relkind)
865  {
866  case RELKIND_RELATION:
867  case RELKIND_MATVIEW:
868  case RELKIND_INDEX:
869  case RELKIND_TOASTVALUE:
870  /* The relation is real, but as yet empty */
871  new_rel_reltup->relpages = 0;
872  new_rel_reltup->reltuples = 0;
873  new_rel_reltup->relallvisible = 0;
874  break;
875  case RELKIND_SEQUENCE:
876  /* Sequences always have a known size */
877  new_rel_reltup->relpages = 1;
878  new_rel_reltup->reltuples = 1;
879  new_rel_reltup->relallvisible = 0;
880  break;
881  default:
882  /* Views, etc, have no disk storage */
883  new_rel_reltup->relpages = 0;
884  new_rel_reltup->reltuples = 0;
885  new_rel_reltup->relallvisible = 0;
886  break;
887  }
888 
889  /* Initialize relfrozenxid and relminmxid */
890  if (relkind == RELKIND_RELATION ||
891  relkind == RELKIND_MATVIEW ||
892  relkind == RELKIND_TOASTVALUE)
893  {
894  /*
895  * Initialize to the minimum XID that could put tuples in the table.
896  * We know that no xacts older than RecentXmin are still running, so
897  * that will do.
898  */
899  new_rel_reltup->relfrozenxid = RecentXmin;
900 
901  /*
902  * Similarly, initialize the minimum Multixact to the first value that
903  * could possibly be stored in tuples in the table. Running
904  * transactions could reuse values from their local cache, so we are
905  * careful to consider all currently running multis.
906  *
907  * XXX this could be refined further, but is it worth the hassle?
908  */
909  new_rel_reltup->relminmxid = GetOldestMultiXactId();
910  }
911  else
912  {
913  /*
914  * Other relation types will not contain XIDs, so set relfrozenxid to
915  * InvalidTransactionId. (Note: a sequence does contain a tuple, but
916  * we force its xmin to be FrozenTransactionId always; see
917  * commands/sequence.c.)
918  */
919  new_rel_reltup->relfrozenxid = InvalidTransactionId;
920  new_rel_reltup->relminmxid = InvalidMultiXactId;
921  }
922 
923  new_rel_reltup->relowner = relowner;
924  new_rel_reltup->reltype = new_type_oid;
925  new_rel_reltup->reloftype = reloftype;
926 
927  /* relispartition is always set by updating this tuple later */
928  new_rel_reltup->relispartition = false;
929 
930  new_rel_desc->rd_att->tdtypeid = new_type_oid;
931 
932  /* Now build and insert the tuple */
933  InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid,
934  relacl, reloptions);
935 }
936 
937 
938 /* --------------------------------
939  * AddNewRelationType -
940  *
941  * define a composite type corresponding to the new relation
942  * --------------------------------
943  */
944 static ObjectAddress
945 AddNewRelationType(const char *typeName,
946  Oid typeNamespace,
947  Oid new_rel_oid,
948  char new_rel_kind,
949  Oid ownerid,
950  Oid new_row_type,
951  Oid new_array_type)
952 {
953  return
954  TypeCreate(new_row_type, /* optional predetermined OID */
955  typeName, /* type name */
956  typeNamespace, /* type namespace */
957  new_rel_oid, /* relation oid */
958  new_rel_kind, /* relation kind */
959  ownerid, /* owner's ID */
960  -1, /* internal size (varlena) */
961  TYPTYPE_COMPOSITE, /* type-type (composite) */
962  TYPCATEGORY_COMPOSITE, /* type-category (ditto) */
963  false, /* composite types are never preferred */
964  DEFAULT_TYPDELIM, /* default array delimiter */
965  F_RECORD_IN, /* input procedure */
966  F_RECORD_OUT, /* output procedure */
967  F_RECORD_RECV, /* receive procedure */
968  F_RECORD_SEND, /* send procedure */
969  InvalidOid, /* typmodin procedure - none */
970  InvalidOid, /* typmodout procedure - none */
971  InvalidOid, /* analyze procedure - default */
972  InvalidOid, /* array element type - irrelevant */
973  false, /* this is not an array type */
974  new_array_type, /* array type if any */
975  InvalidOid, /* domain base type - irrelevant */
976  NULL, /* default value - none */
977  NULL, /* default binary representation */
978  false, /* passed by reference */
979  'd', /* alignment - must be the largest! */
980  'x', /* fully TOASTable */
981  -1, /* typmod */
982  0, /* array dimensions for typBaseType */
983  false, /* Type NOT NULL */
984  InvalidOid); /* rowtypes never have a collation */
985 }
986 
987 /* --------------------------------
988  * heap_create_with_catalog
989  *
990  * creates a new cataloged relation. see comments above.
991  *
992  * Arguments:
993  * relname: name to give to new rel
994  * relnamespace: OID of namespace it goes in
995  * reltablespace: OID of tablespace it goes in
996  * relid: OID to assign to new rel, or InvalidOid to select a new OID
997  * reltypeid: OID to assign to rel's rowtype, or InvalidOid to select one
998  * reloftypeid: if a typed table, OID of underlying type; else InvalidOid
999  * ownerid: OID of new rel's owner
1000  * tupdesc: tuple descriptor (source of column definitions)
1001  * cooked_constraints: list of precooked check constraints and defaults
1002  * relkind: relkind for new rel
1003  * relpersistence: rel's persistence status (permanent, temp, or unlogged)
1004  * shared_relation: true if it's to be a shared relation
1005  * mapped_relation: true if the relation will use the relfilenode map
1006  * oidislocal: true if oid column (if any) should be marked attislocal
1007  * oidinhcount: attinhcount to assign to oid column (if any)
1008  * oncommit: ON COMMIT marking (only relevant if it's a temp table)
1009  * reloptions: reloptions in Datum form, or (Datum) 0 if none
1010  * use_user_acl: true if should look for user-defined default permissions;
1011  * if false, relacl is always set NULL
1012  * allow_system_table_mods: true to allow creation in system namespaces
1013  * is_internal: is this a system-generated catalog?
1014  *
1015  * Output parameters:
1016  * typaddress: if not null, gets the object address of the new pg_type entry
1017  *
1018  * Returns the OID of the new relation
1019  * --------------------------------
1020  */
1021 Oid
1022 heap_create_with_catalog(const char *relname,
1023  Oid relnamespace,
1024  Oid reltablespace,
1025  Oid relid,
1026  Oid reltypeid,
1027  Oid reloftypeid,
1028  Oid ownerid,
1029  TupleDesc tupdesc,
1030  List *cooked_constraints,
1031  char relkind,
1032  char relpersistence,
1033  bool shared_relation,
1034  bool mapped_relation,
1035  bool oidislocal,
1036  int oidinhcount,
1037  OnCommitAction oncommit,
1038  Datum reloptions,
1039  bool use_user_acl,
1040  bool allow_system_table_mods,
1041  bool is_internal,
1042  ObjectAddress *typaddress)
1043 {
1044  Relation pg_class_desc;
1045  Relation new_rel_desc;
1046  Acl *relacl;
1047  Oid existing_relid;
1048  Oid old_type_oid;
1049  Oid new_type_oid;
1050  ObjectAddress new_type_addr;
1051  Oid new_array_oid = InvalidOid;
1052 
1053  pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);
1054 
1055  /*
1056  * sanity checks
1057  */
1059 
1060  CheckAttributeNamesTypes(tupdesc, relkind, allow_system_table_mods);
1061 
1062  /*
1063  * This would fail later on anyway, if the relation already exists. But
1064  * by catching it here we can emit a nicer error message.
1065  */
1066  existing_relid = get_relname_relid(relname, relnamespace);
1067  if (existing_relid != InvalidOid)
1068  ereport(ERROR,
1069  (errcode(ERRCODE_DUPLICATE_TABLE),
1070  errmsg("relation \"%s\" already exists", relname)));
1071 
1072  /*
1073  * Since we are going to create a rowtype as well, also check for
1074  * collision with an existing type name. If there is one and it's an
1075  * autogenerated array, we can rename it out of the way; otherwise we can
1076  * at least give a good error message.
1077  */
1078  old_type_oid = GetSysCacheOid2(TYPENAMENSP,
1079  CStringGetDatum(relname),
1080  ObjectIdGetDatum(relnamespace));
1081  if (OidIsValid(old_type_oid))
1082  {
1083  if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
1084  ereport(ERROR,
1086  errmsg("type \"%s\" already exists", relname),
1087  errhint("A relation has an associated type of the same name, "
1088  "so you must use a name that doesn't conflict "
1089  "with any existing type.")));
1090  }
1091 
1092  /*
1093  * Shared relations must be in pg_global (last-ditch check)
1094  */
1095  if (shared_relation && reltablespace != GLOBALTABLESPACE_OID)
1096  elog(ERROR, "shared relations must be placed in pg_global tablespace");
1097 
1098  /*
1099  * Allocate an OID for the relation, unless we were told what to use.
1100  *
1101  * The OID will be the relfilenode as well, so make sure it doesn't
1102  * collide with either pg_class OIDs or existing physical files.
1103  */
1104  if (!OidIsValid(relid))
1105  {
1106  /* Use binary-upgrade override for pg_class.oid/relfilenode? */
1107  if (IsBinaryUpgrade &&
1108  (relkind == RELKIND_RELATION || relkind == RELKIND_SEQUENCE ||
1109  relkind == RELKIND_VIEW || relkind == RELKIND_MATVIEW ||
1110  relkind == RELKIND_COMPOSITE_TYPE || relkind == RELKIND_FOREIGN_TABLE ||
1111  relkind == RELKIND_PARTITIONED_TABLE))
1112  {
1114  ereport(ERROR,
1115  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1116  errmsg("pg_class heap OID value not set when in binary upgrade mode")));
1117 
1120  }
1121  /* There might be no TOAST table, so we have to test for it. */
1122  else if (IsBinaryUpgrade &&
1124  relkind == RELKIND_TOASTVALUE)
1125  {
1128  }
1129  else
1130  relid = GetNewRelFileNode(reltablespace, pg_class_desc,
1131  relpersistence);
1132  }
1133 
1134  /*
1135  * Determine the relation's initial permissions.
1136  */
1137  if (use_user_acl)
1138  {
1139  switch (relkind)
1140  {
1141  case RELKIND_RELATION:
1142  case RELKIND_VIEW:
1143  case RELKIND_MATVIEW:
1144  case RELKIND_FOREIGN_TABLE:
1146  relacl = get_user_default_acl(OBJECT_TABLE, ownerid,
1147  relnamespace);
1148  break;
1149  case RELKIND_SEQUENCE:
1150  relacl = get_user_default_acl(OBJECT_SEQUENCE, ownerid,
1151  relnamespace);
1152  break;
1153  default:
1154  relacl = NULL;
1155  break;
1156  }
1157  }
1158  else
1159  relacl = NULL;
1160 
1161  /*
1162  * Create the relcache entry (mostly dummy at this point) and the physical
1163  * disk file. (If we fail further down, it's the smgr's responsibility to
1164  * remove the disk file again.)
1165  */
1166  new_rel_desc = heap_create(relname,
1167  relnamespace,
1168  reltablespace,
1169  relid,
1170  InvalidOid,
1171  tupdesc,
1172  relkind,
1173  relpersistence,
1174  shared_relation,
1175  mapped_relation,
1176  allow_system_table_mods);
1177 
1178  Assert(relid == RelationGetRelid(new_rel_desc));
1179 
1180  /*
1181  * Decide whether to create an array type over the relation's rowtype. We
1182  * do not create any array types for system catalogs (ie, those made
1183  * during initdb). We do not create them where the use of a relation as
1184  * such is an implementation detail: toast tables, sequences and indexes.
1185  */
1186  if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
1187  relkind == RELKIND_VIEW ||
1188  relkind == RELKIND_MATVIEW ||
1189  relkind == RELKIND_FOREIGN_TABLE ||
1190  relkind == RELKIND_COMPOSITE_TYPE ||
1191  relkind == RELKIND_PARTITIONED_TABLE))
1192  new_array_oid = AssignTypeArrayOid();
1193 
1194  /*
1195  * Since defining a relation also defines a complex type, we add a new
1196  * system type corresponding to the new relation. The OID of the type can
1197  * be preselected by the caller, but if reltypeid is InvalidOid, we'll
1198  * generate a new OID for it.
1199  *
1200  * NOTE: we could get a unique-index failure here, in case someone else is
1201  * creating the same type name in parallel but hadn't committed yet when
1202  * we checked for a duplicate name above.
1203  */
1204  new_type_addr = AddNewRelationType(relname,
1205  relnamespace,
1206  relid,
1207  relkind,
1208  ownerid,
1209  reltypeid,
1210  new_array_oid);
1211  new_type_oid = new_type_addr.objectId;
1212  if (typaddress)
1213  *typaddress = new_type_addr;
1214 
1215  /*
1216  * Now make the array type if wanted.
1217  */
1218  if (OidIsValid(new_array_oid))
1219  {
1220  char *relarrayname;
1221 
1222  relarrayname = makeArrayTypeName(relname, relnamespace);
1223 
1224  TypeCreate(new_array_oid, /* force the type's OID to this */
1225  relarrayname, /* Array type name */
1226  relnamespace, /* Same namespace as parent */
1227  InvalidOid, /* Not composite, no relationOid */
1228  0, /* relkind, also N/A here */
1229  ownerid, /* owner's ID */
1230  -1, /* Internal size (varlena) */
1231  TYPTYPE_BASE, /* Not composite - typelem is */
1232  TYPCATEGORY_ARRAY, /* type-category (array) */
1233  false, /* array types are never preferred */
1234  DEFAULT_TYPDELIM, /* default array delimiter */
1235  F_ARRAY_IN, /* array input proc */
1236  F_ARRAY_OUT, /* array output proc */
1237  F_ARRAY_RECV, /* array recv (bin) proc */
1238  F_ARRAY_SEND, /* array send (bin) proc */
1239  InvalidOid, /* typmodin procedure - none */
1240  InvalidOid, /* typmodout procedure - none */
1241  F_ARRAY_TYPANALYZE, /* array analyze procedure */
1242  new_type_oid, /* array element type - the rowtype */
1243  true, /* yes, this is an array type */
1244  InvalidOid, /* this has no array type */
1245  InvalidOid, /* domain base type - irrelevant */
1246  NULL, /* default value - none */
1247  NULL, /* default binary representation */
1248  false, /* passed by reference */
1249  'd', /* alignment - must be the largest! */
1250  'x', /* fully TOASTable */
1251  -1, /* typmod */
1252  0, /* array dimensions for typBaseType */
1253  false, /* Type NOT NULL */
1254  InvalidOid); /* rowtypes never have a collation */
1255 
1256  pfree(relarrayname);
1257  }
1258 
1259  /*
1260  * now create an entry in pg_class for the relation.
1261  *
1262  * NOTE: we could get a unique-index failure here, in case someone else is
1263  * creating the same relation name in parallel but hadn't committed yet
1264  * when we checked for a duplicate name above.
1265  */
1266  AddNewRelationTuple(pg_class_desc,
1267  new_rel_desc,
1268  relid,
1269  new_type_oid,
1270  reloftypeid,
1271  ownerid,
1272  relkind,
1273  PointerGetDatum(relacl),
1274  reloptions);
1275 
1276  /*
1277  * now add tuples to pg_attribute for the attributes in our new relation.
1278  */
1279  AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind,
1280  oidislocal, oidinhcount);
1281 
1282  /*
1283  * Make a dependency link to force the relation to be deleted if its
1284  * namespace is. Also make a dependency link to its owner, as well as
1285  * dependencies for any roles mentioned in the default ACL.
1286  *
1287  * For composite types, these dependencies are tracked for the pg_type
1288  * entry, so we needn't record them here. Likewise, TOAST tables don't
1289  * need a namespace dependency (they live in a pinned namespace) nor an
1290  * owner dependency (they depend indirectly through the parent table), nor
1291  * should they have any ACL entries. The same applies for extension
1292  * dependencies.
1293  *
1294  * Also, skip this in bootstrap mode, since we don't make dependencies
1295  * while bootstrapping.
1296  */
1297  if (relkind != RELKIND_COMPOSITE_TYPE &&
1298  relkind != RELKIND_TOASTVALUE &&
1300  {
1301  ObjectAddress myself,
1302  referenced;
1303 
1304  myself.classId = RelationRelationId;
1305  myself.objectId = relid;
1306  myself.objectSubId = 0;
1307  referenced.classId = NamespaceRelationId;
1308  referenced.objectId = relnamespace;
1309  referenced.objectSubId = 0;
1310  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1311 
1313 
1314  recordDependencyOnCurrentExtension(&myself, false);
1315 
1316  if (reloftypeid)
1317  {
1318  referenced.classId = TypeRelationId;
1319  referenced.objectId = reloftypeid;
1320  referenced.objectSubId = 0;
1321  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1322  }
1323 
1324  if (relacl != NULL)
1325  {
1326  int nnewmembers;
1327  Oid *newmembers;
1328 
1329  nnewmembers = aclmembers(relacl, &newmembers);
1331  ownerid,
1332  0, NULL,
1333  nnewmembers, newmembers);
1334  }
1335  }
1336 
1337  /* Post creation hook for new relation */
1338  InvokeObjectPostCreateHookArg(RelationRelationId, relid, 0, is_internal);
1339 
1340  /*
1341  * Store any supplied constraints and defaults.
1342  *
1343  * NB: this may do a CommandCounterIncrement and rebuild the relcache
1344  * entry, so the relation must be valid and self-consistent at this point.
1345  * In particular, there are not yet constraints and defaults anywhere.
1346  */
1347  StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
1348 
1349  /*
1350  * If there's a special on-commit action, remember it
1351  */
1352  if (oncommit != ONCOMMIT_NOOP)
1353  register_on_commit_action(relid, oncommit);
1354 
1355  /*
1356  * Unlogged objects need an init fork, except for partitioned tables which
1357  * have no storage at all.
1358  */
1359  if (relpersistence == RELPERSISTENCE_UNLOGGED &&
1360  relkind != RELKIND_PARTITIONED_TABLE)
1361  heap_create_init_fork(new_rel_desc);
1362 
1363  /*
1364  * ok, the relation has been cataloged, so close our relations and return
1365  * the OID of the newly created relation.
1366  */
1367  heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
1368  heap_close(pg_class_desc, RowExclusiveLock);
1369 
1370  return relid;
1371 }
1372 
1373 /*
1374  * Set up an init fork for an unlogged table so that it can be correctly
1375  * reinitialized on restart. An immediate sync is required even if the
1376  * page has been logged, because the write did not go through
1377  * shared_buffers and therefore a concurrent checkpoint may have moved
1378  * the redo pointer past our xlog record. Recovery may as well remove it
1379  * while replaying, for example, XLOG_DBASE_CREATE or XLOG_TBLSPC_CREATE
1380  * record. Therefore, logging is necessary even if wal_level=minimal.
1381  */
1382 void
1384 {
1385  Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
1386  rel->rd_rel->relkind == RELKIND_MATVIEW ||
1387  rel->rd_rel->relkind == RELKIND_TOASTVALUE);
1388  RelationOpenSmgr(rel);
1389  smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
1392 }
1393 
1394 /*
1395  * RelationRemoveInheritance
1396  *
1397  * Formerly, this routine checked for child relations and aborted the
1398  * deletion if any were found. Now we rely on the dependency mechanism
1399  * to check for or delete child relations. By the time we get here,
1400  * there are no children and we need only remove any pg_inherits rows
1401  * linking this relation to its parent(s).
1402  */
1403 static void
1405 {
1406  Relation catalogRelation;
1407  SysScanDesc scan;
1408  ScanKeyData key;
1409  HeapTuple tuple;
1410 
1411  catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
1412 
1413  ScanKeyInit(&key,
1415  BTEqualStrategyNumber, F_OIDEQ,
1416  ObjectIdGetDatum(relid));
1417 
1418  scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId, true,
1419  NULL, 1, &key);
1420 
1421  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1422  CatalogTupleDelete(catalogRelation, &tuple->t_self);
1423 
1424  systable_endscan(scan);
1425  heap_close(catalogRelation, RowExclusiveLock);
1426 }
1427 
1428 /*
1429  * DeleteRelationTuple
1430  *
1431  * Remove pg_class row for the given relid.
1432  *
1433  * Note: this is shared by relation deletion and index deletion. It's
1434  * not intended for use anyplace else.
1435  */
1436 void
1438 {
1439  Relation pg_class_desc;
1440  HeapTuple tup;
1441 
1442  /* Grab an appropriate lock on the pg_class relation */
1443  pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);
1444 
1445  tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1446  if (!HeapTupleIsValid(tup))
1447  elog(ERROR, "cache lookup failed for relation %u", relid);
1448 
1449  /* delete the relation tuple from pg_class, and finish up */
1450  CatalogTupleDelete(pg_class_desc, &tup->t_self);
1451 
1452  ReleaseSysCache(tup);
1453 
1454  heap_close(pg_class_desc, RowExclusiveLock);
1455 }
1456 
1457 /*
1458  * DeleteAttributeTuples
1459  *
1460  * Remove pg_attribute rows for the given relid.
1461  *
1462  * Note: this is shared by relation deletion and index deletion. It's
1463  * not intended for use anyplace else.
1464  */
1465 void
1467 {
1468  Relation attrel;
1469  SysScanDesc scan;
1470  ScanKeyData key[1];
1471  HeapTuple atttup;
1472 
1473  /* Grab an appropriate lock on the pg_attribute relation */
1475 
1476  /* Use the index to scan only attributes of the target relation */
1477  ScanKeyInit(&key[0],
1479  BTEqualStrategyNumber, F_OIDEQ,
1480  ObjectIdGetDatum(relid));
1481 
1482  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1483  NULL, 1, key);
1484 
1485  /* Delete all the matching tuples */
1486  while ((atttup = systable_getnext(scan)) != NULL)
1487  CatalogTupleDelete(attrel, &atttup->t_self);
1488 
1489  /* Clean up after the scan */
1490  systable_endscan(scan);
1491  heap_close(attrel, RowExclusiveLock);
1492 }
1493 
1494 /*
1495  * DeleteSystemAttributeTuples
1496  *
1497  * Remove pg_attribute rows for system columns of the given relid.
1498  *
1499  * Note: this is only used when converting a table to a view. Views don't
1500  * have system columns, so we should remove them from pg_attribute.
1501  */
1502 void
1504 {
1505  Relation attrel;
1506  SysScanDesc scan;
1507  ScanKeyData key[2];
1508  HeapTuple atttup;
1509 
1510  /* Grab an appropriate lock on the pg_attribute relation */
1512 
1513  /* Use the index to scan only system attributes of the target relation */
1514  ScanKeyInit(&key[0],
1516  BTEqualStrategyNumber, F_OIDEQ,
1517  ObjectIdGetDatum(relid));
1518  ScanKeyInit(&key[1],
1520  BTLessEqualStrategyNumber, F_INT2LE,
1521  Int16GetDatum(0));
1522 
1523  scan = systable_beginscan(attrel, AttributeRelidNumIndexId, true,
1524  NULL, 2, key);
1525 
1526  /* Delete all the matching tuples */
1527  while ((atttup = systable_getnext(scan)) != NULL)
1528  CatalogTupleDelete(attrel, &atttup->t_self);
1529 
1530  /* Clean up after the scan */
1531  systable_endscan(scan);
1532  heap_close(attrel, RowExclusiveLock);
1533 }
1534 
1535 /*
1536  * RemoveAttributeById
1537  *
1538  * This is the guts of ALTER TABLE DROP COLUMN: actually mark the attribute
1539  * deleted in pg_attribute. We also remove pg_statistic entries for it.
1540  * (Everything else needed, such as getting rid of any pg_attrdef entry,
1541  * is handled by dependency.c.)
1542  */
1543 void
1545 {
1546  Relation rel;
1547  Relation attr_rel;
1548  HeapTuple tuple;
1549  Form_pg_attribute attStruct;
1550  char newattname[NAMEDATALEN];
1551 
1552  /*
1553  * Grab an exclusive lock on the target table, which we will NOT release
1554  * until end of transaction. (In the simple case where we are directly
1555  * dropping this column, AlterTableDropColumn already did this ... but
1556  * when cascading from a drop of some other object, we may not have any
1557  * lock.)
1558  */
1559  rel = relation_open(relid, AccessExclusiveLock);
1560 
1562 
1563  tuple = SearchSysCacheCopy2(ATTNUM,
1564  ObjectIdGetDatum(relid),
1565  Int16GetDatum(attnum));
1566  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1567  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1568  attnum, relid);
1569  attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
1570 
1571  if (attnum < 0)
1572  {
1573  /* System attribute (probably OID) ... just delete the row */
1574 
1575  CatalogTupleDelete(attr_rel, &tuple->t_self);
1576  }
1577  else
1578  {
1579  /* Dropping user attributes is lots harder */
1580 
1581  /* Mark the attribute as dropped */
1582  attStruct->attisdropped = true;
1583 
1584  /*
1585  * Set the type OID to invalid. A dropped attribute's type link
1586  * cannot be relied on (once the attribute is dropped, the type might
1587  * be too). Fortunately we do not need the type row --- the only
1588  * really essential information is the type's typlen and typalign,
1589  * which are preserved in the attribute's attlen and attalign. We set
1590  * atttypid to zero here as a means of catching code that incorrectly
1591  * expects it to be valid.
1592  */
1593  attStruct->atttypid = InvalidOid;
1594 
1595  /* Remove any NOT NULL constraint the column may have */
1596  attStruct->attnotnull = false;
1597 
1598  /* We don't want to keep stats for it anymore */
1599  attStruct->attstattarget = 0;
1600 
1601  /*
1602  * Change the column name to something that isn't likely to conflict
1603  */
1604  snprintf(newattname, sizeof(newattname),
1605  "........pg.dropped.%d........", attnum);
1606  namestrcpy(&(attStruct->attname), newattname);
1607 
1608  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1609  }
1610 
1611  /*
1612  * Because updating the pg_attribute row will trigger a relcache flush for
1613  * the target relation, we need not do anything else to notify other
1614  * backends of the change.
1615  */
1616 
1617  heap_close(attr_rel, RowExclusiveLock);
1618 
1619  if (attnum > 0)
1620  RemoveStatistics(relid, attnum);
1621 
1622  relation_close(rel, NoLock);
1623 }
1624 
1625 /*
1626  * RemoveAttrDefault
1627  *
1628  * If the specified relation/attribute has a default, remove it.
1629  * (If no default, raise error if complain is true, else return quietly.)
1630  */
1631 void
1633  DropBehavior behavior, bool complain, bool internal)
1634 {
1635  Relation attrdef_rel;
1636  ScanKeyData scankeys[2];
1637  SysScanDesc scan;
1638  HeapTuple tuple;
1639  bool found = false;
1640 
1642 
1643  ScanKeyInit(&scankeys[0],
1645  BTEqualStrategyNumber, F_OIDEQ,
1646  ObjectIdGetDatum(relid));
1647  ScanKeyInit(&scankeys[1],
1649  BTEqualStrategyNumber, F_INT2EQ,
1650  Int16GetDatum(attnum));
1651 
1652  scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1653  NULL, 2, scankeys);
1654 
1655  /* There should be at most one matching tuple, but we loop anyway */
1656  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1657  {
1659 
1660  object.classId = AttrDefaultRelationId;
1661  object.objectId = HeapTupleGetOid(tuple);
1662  object.objectSubId = 0;
1663 
1664  performDeletion(&object, behavior,
1665  internal ? PERFORM_DELETION_INTERNAL : 0);
1666 
1667  found = true;
1668  }
1669 
1670  systable_endscan(scan);
1671  heap_close(attrdef_rel, RowExclusiveLock);
1672 
1673  if (complain && !found)
1674  elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1675  relid, attnum);
1676 }
1677 
1678 /*
1679  * RemoveAttrDefaultById
1680  *
1681  * Remove a pg_attrdef entry specified by OID. This is the guts of
1682  * attribute-default removal. Note it should be called via performDeletion,
1683  * not directly.
1684  */
1685 void
1687 {
1688  Relation attrdef_rel;
1689  Relation attr_rel;
1690  Relation myrel;
1691  ScanKeyData scankeys[1];
1692  SysScanDesc scan;
1693  HeapTuple tuple;
1694  Oid myrelid;
1695  AttrNumber myattnum;
1696 
1697  /* Grab an appropriate lock on the pg_attrdef relation */
1699 
1700  /* Find the pg_attrdef tuple */
1701  ScanKeyInit(&scankeys[0],
1703  BTEqualStrategyNumber, F_OIDEQ,
1704  ObjectIdGetDatum(attrdefId));
1705 
1706  scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1707  NULL, 1, scankeys);
1708 
1709  tuple = systable_getnext(scan);
1710  if (!HeapTupleIsValid(tuple))
1711  elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1712 
1713  myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1714  myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1715 
1716  /* Get an exclusive lock on the relation owning the attribute */
1717  myrel = relation_open(myrelid, AccessExclusiveLock);
1718 
1719  /* Now we can delete the pg_attrdef row */
1720  CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1721 
1722  systable_endscan(scan);
1723  heap_close(attrdef_rel, RowExclusiveLock);
1724 
1725  /* Fix the pg_attribute row */
1727 
1728  tuple = SearchSysCacheCopy2(ATTNUM,
1729  ObjectIdGetDatum(myrelid),
1730  Int16GetDatum(myattnum));
1731  if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1732  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1733  myattnum, myrelid);
1734 
1735  ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1736 
1737  CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1738 
1739  /*
1740  * Our update of the pg_attribute row will force a relcache rebuild, so
1741  * there's nothing else to do here.
1742  */
1743  heap_close(attr_rel, RowExclusiveLock);
1744 
1745  /* Keep lock on attribute's rel until end of xact */
1746  relation_close(myrel, NoLock);
1747 }
1748 
1749 /*
1750  * heap_drop_with_catalog - removes specified relation from catalogs
1751  *
1752  * Note that this routine is not responsible for dropping objects that are
1753  * linked to the pg_class entry via dependencies (for example, indexes and
1754  * constraints). Those are deleted by the dependency-tracing logic in
1755  * dependency.c before control gets here. In general, therefore, this routine
1756  * should never be called directly; go through performDeletion() instead.
1757  */
1758 void
1760 {
1761  Relation rel;
1762  HeapTuple tuple;
1763  Oid parentOid = InvalidOid,
1764  defaultPartOid = InvalidOid;
1765 
1766  /*
1767  * To drop a partition safely, we must grab exclusive lock on its parent,
1768  * because another backend might be about to execute a query on the parent
1769  * table. If it relies on previously cached partition descriptor, then it
1770  * could attempt to access the just-dropped relation as its partition. We
1771  * must therefore take a table lock strong enough to prevent all queries
1772  * on the table from proceeding until we commit and send out a
1773  * shared-cache-inval notice that will make them update their index lists.
1774  */
1775  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1776  if (!HeapTupleIsValid(tuple))
1777  elog(ERROR, "cache lookup failed for relation %u", relid);
1778  if (((Form_pg_class) GETSTRUCT(tuple))->relispartition)
1779  {
1780  parentOid = get_partition_parent(relid);
1782 
1783  /*
1784  * If this is not the default partition, dropping it will change the
1785  * default partition's partition constraint, so we must lock it.
1786  */
1787  defaultPartOid = get_default_partition_oid(parentOid);
1788  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1789  LockRelationOid(defaultPartOid, AccessExclusiveLock);
1790  }
1791 
1792  ReleaseSysCache(tuple);
1793 
1794  /*
1795  * Open and lock the relation.
1796  */
1797  rel = relation_open(relid, AccessExclusiveLock);
1798 
1799  /*
1800  * There can no longer be anyone *else* touching the relation, but we
1801  * might still have open queries or cursors, or pending trigger events, in
1802  * our own session.
1803  */
1804  CheckTableNotInUse(rel, "DROP TABLE");
1805 
1806  /*
1807  * This effectively deletes all rows in the table, and may be done in a
1808  * serializable transaction. In that case we must record a rw-conflict in
1809  * to this transaction from each transaction holding a predicate lock on
1810  * the table.
1811  */
1813 
1814  /*
1815  * Delete pg_foreign_table tuple first.
1816  */
1817  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1818  {
1819  Relation rel;
1820  HeapTuple tuple;
1821 
1823 
1825  if (!HeapTupleIsValid(tuple))
1826  elog(ERROR, "cache lookup failed for foreign table %u", relid);
1827 
1828  CatalogTupleDelete(rel, &tuple->t_self);
1829 
1830  ReleaseSysCache(tuple);
1832  }
1833 
1834  /*
1835  * If a partitioned table, delete the pg_partitioned_table tuple.
1836  */
1837  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1839 
1840  /*
1841  * If the relation being dropped is the default partition itself,
1842  * invalidate its entry in pg_partitioned_table.
1843  */
1844  if (relid == defaultPartOid)
1846 
1847  /*
1848  * Schedule unlinking of the relation's physical files at commit.
1849  */
1850  if (rel->rd_rel->relkind != RELKIND_VIEW &&
1851  rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
1852  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1853  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1854  {
1855  RelationDropStorage(rel);
1856  }
1857 
1858  /*
1859  * Close relcache entry, but *keep* AccessExclusiveLock on the relation
1860  * until transaction commit. This ensures no one else will try to do
1861  * something with the doomed relation.
1862  */
1863  relation_close(rel, NoLock);
1864 
1865  /*
1866  * Remove any associated relation synchronization states.
1867  */
1869 
1870  /*
1871  * Forget any ON COMMIT action for the rel
1872  */
1873  remove_on_commit_action(relid);
1874 
1875  /*
1876  * Flush the relation from the relcache. We want to do this before
1877  * starting to remove catalog entries, just to be certain that no relcache
1878  * entry rebuild will happen partway through. (That should not really
1879  * matter, since we don't do CommandCounterIncrement here, but let's be
1880  * safe.)
1881  */
1882  RelationForgetRelation(relid);
1883 
1884  /*
1885  * remove inheritance information
1886  */
1888 
1889  /*
1890  * delete statistics
1891  */
1892  RemoveStatistics(relid, 0);
1893 
1894  /*
1895  * delete attribute tuples
1896  */
1897  DeleteAttributeTuples(relid);
1898 
1899  /*
1900  * delete relation tuple
1901  */
1902  DeleteRelationTuple(relid);
1903 
1904  if (OidIsValid(parentOid))
1905  {
1906  /*
1907  * If this is not the default partition, the partition constraint of
1908  * the default partition has changed to include the portion of the key
1909  * space previously covered by the dropped partition.
1910  */
1911  if (OidIsValid(defaultPartOid) && relid != defaultPartOid)
1912  CacheInvalidateRelcacheByRelid(defaultPartOid);
1913 
1914  /*
1915  * Invalidate the parent's relcache so that the partition is no longer
1916  * included in its partition descriptor.
1917  */
1918  CacheInvalidateRelcacheByRelid(parentOid);
1919  /* keep the lock */
1920  }
1921 }
1922 
1923 
1924 /*
1925  * Store a default expression for column attnum of relation rel.
1926  *
1927  * Returns the OID of the new pg_attrdef tuple.
1928  */
1929 Oid
1931  Node *expr, bool is_internal)
1932 {
1933  char *adbin;
1934  char *adsrc;
1935  Relation adrel;
1936  HeapTuple tuple;
1937  Datum values[4];
1938  static bool nulls[4] = {false, false, false, false};
1939  Relation attrrel;
1940  HeapTuple atttup;
1941  Form_pg_attribute attStruct;
1942  Oid attrdefOid;
1943  ObjectAddress colobject,
1944  defobject;
1945 
1946  /*
1947  * Flatten expression to string form for storage.
1948  */
1949  adbin = nodeToString(expr);
1950 
1951  /*
1952  * Also deparse it to form the mostly-obsolete adsrc field.
1953  */
1954  adsrc = deparse_expression(expr,
1956  RelationGetRelid(rel)),
1957  false, false);
1958 
1959  /*
1960  * Make the pg_attrdef entry.
1961  */
1962  values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
1963  values[Anum_pg_attrdef_adnum - 1] = attnum;
1964  values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
1965  values[Anum_pg_attrdef_adsrc - 1] = CStringGetTextDatum(adsrc);
1966 
1968 
1969  tuple = heap_form_tuple(adrel->rd_att, values, nulls);
1970  attrdefOid = CatalogTupleInsert(adrel, tuple);
1971 
1972  defobject.classId = AttrDefaultRelationId;
1973  defobject.objectId = attrdefOid;
1974  defobject.objectSubId = 0;
1975 
1976  heap_close(adrel, RowExclusiveLock);
1977 
1978  /* now can free some of the stuff allocated above */
1981  heap_freetuple(tuple);
1982  pfree(adbin);
1983  pfree(adsrc);
1984 
1985  /*
1986  * Update the pg_attribute entry for the column to show that a default
1987  * exists.
1988  */
1990  atttup = SearchSysCacheCopy2(ATTNUM,
1992  Int16GetDatum(attnum));
1993  if (!HeapTupleIsValid(atttup))
1994  elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1995  attnum, RelationGetRelid(rel));
1996  attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
1997  if (!attStruct->atthasdef)
1998  {
1999  attStruct->atthasdef = true;
2000  CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
2001  }
2002  heap_close(attrrel, RowExclusiveLock);
2003  heap_freetuple(atttup);
2004 
2005  /*
2006  * Make a dependency so that the pg_attrdef entry goes away if the column
2007  * (or whole table) is deleted.
2008  */
2009  colobject.classId = RelationRelationId;
2010  colobject.objectId = RelationGetRelid(rel);
2011  colobject.objectSubId = attnum;
2012 
2013  recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
2014 
2015  /*
2016  * Record dependencies on objects used in the expression, too.
2017  */
2018  recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
2019 
2020  /*
2021  * Post creation hook for attribute defaults.
2022  *
2023  * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
2024  * couple of deletion/creation of the attribute's default entry, so the
2025  * callee should check existence of an older version of this entry if it
2026  * needs to distinguish.
2027  */
2029  RelationGetRelid(rel), attnum, is_internal);
2030 
2031  return attrdefOid;
2032 }
2033 
2034 /*
2035  * Store a check-constraint expression for the given relation.
2036  *
2037  * Caller is responsible for updating the count of constraints
2038  * in the pg_class entry for the relation.
2039  *
2040  * The OID of the new constraint is returned.
2041  */
2042 static Oid
2043 StoreRelCheck(Relation rel, const char *ccname, Node *expr,
2044  bool is_validated, bool is_local, int inhcount,
2045  bool is_no_inherit, bool is_internal)
2046 {
2047  char *ccbin;
2048  char *ccsrc;
2049  List *varList;
2050  int keycount;
2051  int16 *attNos;
2052  Oid constrOid;
2053 
2054  /*
2055  * Flatten expression to string form for storage.
2056  */
2057  ccbin = nodeToString(expr);
2058 
2059  /*
2060  * Also deparse it to form the mostly-obsolete consrc field.
2061  */
2062  ccsrc = deparse_expression(expr,
2064  RelationGetRelid(rel)),
2065  false, false);
2066 
2067  /*
2068  * Find columns of rel that are used in expr
2069  *
2070  * NB: pull_var_clause is okay here only because we don't allow subselects
2071  * in check constraints; it would fail to examine the contents of
2072  * subselects.
2073  */
2074  varList = pull_var_clause(expr, 0);
2075  keycount = list_length(varList);
2076 
2077  if (keycount > 0)
2078  {
2079  ListCell *vl;
2080  int i = 0;
2081 
2082  attNos = (int16 *) palloc(keycount * sizeof(int16));
2083  foreach(vl, varList)
2084  {
2085  Var *var = (Var *) lfirst(vl);
2086  int j;
2087 
2088  for (j = 0; j < i; j++)
2089  if (attNos[j] == var->varattno)
2090  break;
2091  if (j == i)
2092  attNos[i++] = var->varattno;
2093  }
2094  keycount = i;
2095  }
2096  else
2097  attNos = NULL;
2098 
2099  /*
2100  * Partitioned tables do not contain any rows themselves, so a NO INHERIT
2101  * constraint makes no sense.
2102  */
2103  if (is_no_inherit &&
2104  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2105  ereport(ERROR,
2106  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2107  errmsg("cannot add NO INHERIT constraint to partitioned table \"%s\"",
2108  RelationGetRelationName(rel))));
2109 
2110  /*
2111  * Create the Check Constraint
2112  */
2113  constrOid =
2114  CreateConstraintEntry(ccname, /* Constraint Name */
2115  RelationGetNamespace(rel), /* namespace */
2116  CONSTRAINT_CHECK, /* Constraint Type */
2117  false, /* Is Deferrable */
2118  false, /* Is Deferred */
2119  is_validated,
2120  RelationGetRelid(rel), /* relation */
2121  attNos, /* attrs in the constraint */
2122  keycount, /* # attrs in the constraint */
2123  InvalidOid, /* not a domain constraint */
2124  InvalidOid, /* no associated index */
2125  InvalidOid, /* Foreign key fields */
2126  NULL,
2127  NULL,
2128  NULL,
2129  NULL,
2130  0,
2131  ' ',
2132  ' ',
2133  ' ',
2134  NULL, /* not an exclusion constraint */
2135  expr, /* Tree form of check constraint */
2136  ccbin, /* Binary form of check constraint */
2137  ccsrc, /* Source form of check constraint */
2138  is_local, /* conislocal */
2139  inhcount, /* coninhcount */
2140  is_no_inherit, /* connoinherit */
2141  is_internal); /* internally constructed? */
2142 
2143  pfree(ccbin);
2144  pfree(ccsrc);
2145 
2146  return constrOid;
2147 }
2148 
2149 /*
2150  * Store defaults and constraints (passed as a list of CookedConstraint).
2151  *
2152  * Each CookedConstraint struct is modified to store the new catalog tuple OID.
2153  *
2154  * NOTE: only pre-cooked expressions will be passed this way, which is to
2155  * say expressions inherited from an existing relation. Newly parsed
2156  * expressions can be added later, by direct calls to StoreAttrDefault
2157  * and StoreRelCheck (see AddRelationNewConstraints()).
2158  */
2159 static void
2160 StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
2161 {
2162  int numchecks = 0;
2163  ListCell *lc;
2164 
2165  if (cooked_constraints == NIL)
2166  return; /* nothing to do */
2167 
2168  /*
2169  * Deparsing of constraint expressions will fail unless the just-created
2170  * pg_attribute tuples for this relation are made visible. So, bump the
2171  * command counter. CAUTION: this will cause a relcache entry rebuild.
2172  */
2174 
2175  foreach(lc, cooked_constraints)
2176  {
2177  CookedConstraint *con = (CookedConstraint *) lfirst(lc);
2178 
2179  switch (con->contype)
2180  {
2181  case CONSTR_DEFAULT:
2182  con->conoid = StoreAttrDefault(rel, con->attnum, con->expr,
2183  is_internal);
2184  break;
2185  case CONSTR_CHECK:
2186  con->conoid =
2187  StoreRelCheck(rel, con->name, con->expr,
2188  !con->skip_validation, con->is_local,
2189  con->inhcount, con->is_no_inherit,
2190  is_internal);
2191  numchecks++;
2192  break;
2193  default:
2194  elog(ERROR, "unrecognized constraint type: %d",
2195  (int) con->contype);
2196  }
2197  }
2198 
2199  if (numchecks > 0)
2200  SetRelationNumChecks(rel, numchecks);
2201 }
2202 
2203 /*
2204  * AddRelationNewConstraints
2205  *
2206  * Add new column default expressions and/or constraint check expressions
2207  * to an existing relation. This is defined to do both for efficiency in
2208  * DefineRelation, but of course you can do just one or the other by passing
2209  * empty lists.
2210  *
2211  * rel: relation to be modified
2212  * newColDefaults: list of RawColumnDefault structures
2213  * newConstraints: list of Constraint nodes
2214  * allow_merge: true if check constraints may be merged with existing ones
2215  * is_local: true if definition is local, false if it's inherited
2216  * is_internal: true if result of some internal process, not a user request
2217  *
2218  * All entries in newColDefaults will be processed. Entries in newConstraints
2219  * will be processed only if they are CONSTR_CHECK type.
2220  *
2221  * Returns a list of CookedConstraint nodes that shows the cooked form of
2222  * the default and constraint expressions added to the relation.
2223  *
2224  * NB: caller should have opened rel with AccessExclusiveLock, and should
2225  * hold that lock till end of transaction. Also, we assume the caller has
2226  * done a CommandCounterIncrement if necessary to make the relation's catalog
2227  * tuples visible.
2228  */
2229 List *
2231  List *newColDefaults,
2232  List *newConstraints,
2233  bool allow_merge,
2234  bool is_local,
2235  bool is_internal)
2236 {
2237  List *cookedConstraints = NIL;
2239  TupleConstr *oldconstr;
2240  int numoldchecks;
2241  ParseState *pstate;
2242  RangeTblEntry *rte;
2243  int numchecks;
2244  List *checknames;
2245  ListCell *cell;
2246  Node *expr;
2247  CookedConstraint *cooked;
2248 
2249  /*
2250  * Get info about existing constraints.
2251  */
2252  tupleDesc = RelationGetDescr(rel);
2253  oldconstr = tupleDesc->constr;
2254  if (oldconstr)
2255  numoldchecks = oldconstr->num_check;
2256  else
2257  numoldchecks = 0;
2258 
2259  /*
2260  * Create a dummy ParseState and insert the target relation as its sole
2261  * rangetable entry. We need a ParseState for transformExpr.
2262  */
2263  pstate = make_parsestate(NULL);
2264  rte = addRangeTableEntryForRelation(pstate,
2265  rel,
2266  NULL,
2267  false,
2268  true);
2269  addRTEtoQuery(pstate, rte, true, true, true);
2270 
2271  /*
2272  * Process column default expressions.
2273  */
2274  foreach(cell, newColDefaults)
2275  {
2276  RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell);
2277  Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1);
2278  Oid defOid;
2279 
2280  expr = cookDefault(pstate, colDef->raw_default,
2281  atp->atttypid, atp->atttypmod,
2282  NameStr(atp->attname));
2283 
2284  /*
2285  * If the expression is just a NULL constant, we do not bother to make
2286  * an explicit pg_attrdef entry, since the default behavior is
2287  * equivalent.
2288  *
2289  * Note a nonobvious property of this test: if the column is of a
2290  * domain type, what we'll get is not a bare null Const but a
2291  * CoerceToDomain expr, so we will not discard the default. This is
2292  * critical because the column default needs to be retained to
2293  * override any default that the domain might have.
2294  */
2295  if (expr == NULL ||
2296  (IsA(expr, Const) &&((Const *) expr)->constisnull))
2297  continue;
2298 
2299  defOid = StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
2300 
2301  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2302  cooked->contype = CONSTR_DEFAULT;
2303  cooked->conoid = defOid;
2304  cooked->name = NULL;
2305  cooked->attnum = colDef->attnum;
2306  cooked->expr = expr;
2307  cooked->skip_validation = false;
2308  cooked->is_local = is_local;
2309  cooked->inhcount = is_local ? 0 : 1;
2310  cooked->is_no_inherit = false;
2311  cookedConstraints = lappend(cookedConstraints, cooked);
2312  }
2313 
2314  /*
2315  * Process constraint expressions.
2316  */
2317  numchecks = numoldchecks;
2318  checknames = NIL;
2319  foreach(cell, newConstraints)
2320  {
2321  Constraint *cdef = (Constraint *) lfirst(cell);
2322  char *ccname;
2323  Oid constrOid;
2324 
2325  if (cdef->contype != CONSTR_CHECK)
2326  continue;
2327 
2328  if (cdef->raw_expr != NULL)
2329  {
2330  Assert(cdef->cooked_expr == NULL);
2331 
2332  /*
2333  * Transform raw parsetree to executable expression, and verify
2334  * it's valid as a CHECK constraint.
2335  */
2336  expr = cookConstraint(pstate, cdef->raw_expr,
2338  }
2339  else
2340  {
2341  Assert(cdef->cooked_expr != NULL);
2342 
2343  /*
2344  * Here, we assume the parser will only pass us valid CHECK
2345  * expressions, so we do no particular checking.
2346  */
2347  expr = stringToNode(cdef->cooked_expr);
2348  }
2349 
2350  /*
2351  * Check name uniqueness, or generate a name if none was given.
2352  */
2353  if (cdef->conname != NULL)
2354  {
2355  ListCell *cell2;
2356 
2357  ccname = cdef->conname;
2358  /* Check against other new constraints */
2359  /* Needed because we don't do CommandCounterIncrement in loop */
2360  foreach(cell2, checknames)
2361  {
2362  if (strcmp((char *) lfirst(cell2), ccname) == 0)
2363  ereport(ERROR,
2365  errmsg("check constraint \"%s\" already exists",
2366  ccname)));
2367  }
2368 
2369  /* save name for future checks */
2370  checknames = lappend(checknames, ccname);
2371 
2372  /*
2373  * Check against pre-existing constraints. If we are allowed to
2374  * merge with an existing constraint, there's no more to do here.
2375  * (We omit the duplicate constraint from the result, which is
2376  * what ATAddCheckConstraint wants.)
2377  */
2378  if (MergeWithExistingConstraint(rel, ccname, expr,
2379  allow_merge, is_local,
2380  cdef->initially_valid,
2381  cdef->is_no_inherit))
2382  continue;
2383  }
2384  else
2385  {
2386  /*
2387  * When generating a name, we want to create "tab_col_check" for a
2388  * column constraint and "tab_check" for a table constraint. We
2389  * no longer have any info about the syntactic positioning of the
2390  * constraint phrase, so we approximate this by seeing whether the
2391  * expression references more than one column. (If the user
2392  * played by the rules, the result is the same...)
2393  *
2394  * Note: pull_var_clause() doesn't descend into sublinks, but we
2395  * eliminated those above; and anyway this only needs to be an
2396  * approximate answer.
2397  */
2398  List *vars;
2399  char *colname;
2400 
2401  vars = pull_var_clause(expr, 0);
2402 
2403  /* eliminate duplicates */
2404  vars = list_union(NIL, vars);
2405 
2406  if (list_length(vars) == 1)
2407  colname = get_attname(RelationGetRelid(rel),
2408  ((Var *) linitial(vars))->varattno);
2409  else
2410  colname = NULL;
2411 
2413  colname,
2414  "check",
2415  RelationGetNamespace(rel),
2416  checknames);
2417 
2418  /* save name for future checks */
2419  checknames = lappend(checknames, ccname);
2420  }
2421 
2422  /*
2423  * OK, store it.
2424  */
2425  constrOid =
2426  StoreRelCheck(rel, ccname, expr, cdef->initially_valid, is_local,
2427  is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
2428 
2429  numchecks++;
2430 
2431  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
2432  cooked->contype = CONSTR_CHECK;
2433  cooked->conoid = constrOid;
2434  cooked->name = ccname;
2435  cooked->attnum = 0;
2436  cooked->expr = expr;
2437  cooked->skip_validation = cdef->skip_validation;
2438  cooked->is_local = is_local;
2439  cooked->inhcount = is_local ? 0 : 1;
2440  cooked->is_no_inherit = cdef->is_no_inherit;
2441  cookedConstraints = lappend(cookedConstraints, cooked);
2442  }
2443 
2444  /*
2445  * Update the count of constraints in the relation's pg_class tuple. We do
2446  * this even if there was no change, in order to ensure that an SI update
2447  * message is sent out for the pg_class tuple, which will force other
2448  * backends to rebuild their relcache entries for the rel. (This is
2449  * critical if we added defaults but not constraints.)
2450  */
2451  SetRelationNumChecks(rel, numchecks);
2452 
2453  return cookedConstraints;
2454 }
2455 
2456 /*
2457  * Check for a pre-existing check constraint that conflicts with a proposed
2458  * new one, and either adjust its conislocal/coninhcount settings or throw
2459  * error as needed.
2460  *
2461  * Returns true if merged (constraint is a duplicate), or false if it's
2462  * got a so-far-unique name, or throws error if conflict.
2463  *
2464  * XXX See MergeConstraintsIntoExisting too if you change this code.
2465  */
2466 static bool
2467 MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
2468  bool allow_merge, bool is_local,
2469  bool is_initially_valid,
2470  bool is_no_inherit)
2471 {
2472  bool found;
2473  Relation conDesc;
2474  SysScanDesc conscan;
2475  ScanKeyData skey[2];
2476  HeapTuple tup;
2477 
2478  /* Search for a pg_constraint entry with same name and relation */
2480 
2481  found = false;
2482 
2483  ScanKeyInit(&skey[0],
2485  BTEqualStrategyNumber, F_NAMEEQ,
2486  CStringGetDatum(ccname));
2487 
2488  ScanKeyInit(&skey[1],
2490  BTEqualStrategyNumber, F_OIDEQ,
2492 
2493  conscan = systable_beginscan(conDesc, ConstraintNameNspIndexId, true,
2494  NULL, 2, skey);
2495 
2496  while (HeapTupleIsValid(tup = systable_getnext(conscan)))
2497  {
2499 
2500  if (con->conrelid == RelationGetRelid(rel))
2501  {
2502  /* Found it. Conflicts if not identical check constraint */
2503  if (con->contype == CONSTRAINT_CHECK)
2504  {
2505  Datum val;
2506  bool isnull;
2507 
2508  val = fastgetattr(tup,
2510  conDesc->rd_att, &isnull);
2511  if (isnull)
2512  elog(ERROR, "null conbin for rel %s",
2514  if (equal(expr, stringToNode(TextDatumGetCString(val))))
2515  found = true;
2516  }
2517 
2518  /*
2519  * If the existing constraint is purely inherited (no local
2520  * definition) then interpret addition of a local constraint as a
2521  * legal merge. This allows ALTER ADD CONSTRAINT on parent and
2522  * child tables to be given in either order with same end state.
2523  * However if the relation is a partition, all inherited
2524  * constraints are always non-local, including those that were
2525  * merged.
2526  */
2527  if (is_local && !con->conislocal && !rel->rd_rel->relispartition)
2528  allow_merge = true;
2529 
2530  if (!found || !allow_merge)
2531  ereport(ERROR,
2533  errmsg("constraint \"%s\" for relation \"%s\" already exists",
2534  ccname, RelationGetRelationName(rel))));
2535 
2536  /* If the child constraint is "no inherit" then cannot merge */
2537  if (con->connoinherit)
2538  ereport(ERROR,
2539  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2540  errmsg("constraint \"%s\" conflicts with non-inherited constraint on relation \"%s\"",
2541  ccname, RelationGetRelationName(rel))));
2542 
2543  /*
2544  * Must not change an existing inherited constraint to "no
2545  * inherit" status. That's because inherited constraints should
2546  * be able to propagate to lower-level children.
2547  */
2548  if (con->coninhcount > 0 && is_no_inherit)
2549  ereport(ERROR,
2550  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2551  errmsg("constraint \"%s\" conflicts with inherited constraint on relation \"%s\"",
2552  ccname, RelationGetRelationName(rel))));
2553 
2554  /*
2555  * If the child constraint is "not valid" then cannot merge with a
2556  * valid parent constraint
2557  */
2558  if (is_initially_valid && !con->convalidated)
2559  ereport(ERROR,
2560  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
2561  errmsg("constraint \"%s\" conflicts with NOT VALID constraint on relation \"%s\"",
2562  ccname, RelationGetRelationName(rel))));
2563 
2564  /* OK to update the tuple */
2565  ereport(NOTICE,
2566  (errmsg("merging constraint \"%s\" with inherited definition",
2567  ccname)));
2568 
2569  tup = heap_copytuple(tup);
2570  con = (Form_pg_constraint) GETSTRUCT(tup);
2571 
2572  /*
2573  * In case of partitions, an inherited constraint must be
2574  * inherited only once since it cannot have multiple parents and
2575  * it is never considered local.
2576  */
2577  if (rel->rd_rel->relispartition)
2578  {
2579  con->coninhcount = 1;
2580  con->conislocal = false;
2581  }
2582  else
2583  {
2584  if (is_local)
2585  con->conislocal = true;
2586  else
2587  con->coninhcount++;
2588  }
2589 
2590  if (is_no_inherit)
2591  {
2592  Assert(is_local);
2593  con->connoinherit = true;
2594  }
2595  CatalogTupleUpdate(conDesc, &tup->t_self, tup);
2596  break;
2597  }
2598  }
2599 
2600  systable_endscan(conscan);
2601  heap_close(conDesc, RowExclusiveLock);
2602 
2603  return found;
2604 }
2605 
2606 /*
2607  * Update the count of constraints in the relation's pg_class tuple.
2608  *
2609  * Caller had better hold exclusive lock on the relation.
2610  *
2611  * An important side effect is that a SI update message will be sent out for
2612  * the pg_class tuple, which will force other backends to rebuild their
2613  * relcache entries for the rel. Also, this backend will rebuild its
2614  * own relcache entry at the next CommandCounterIncrement.
2615  */
2616 static void
2617 SetRelationNumChecks(Relation rel, int numchecks)
2618 {
2619  Relation relrel;
2620  HeapTuple reltup;
2621  Form_pg_class relStruct;
2622 
2624  reltup = SearchSysCacheCopy1(RELOID,
2626  if (!HeapTupleIsValid(reltup))
2627  elog(ERROR, "cache lookup failed for relation %u",
2628  RelationGetRelid(rel));
2629  relStruct = (Form_pg_class) GETSTRUCT(reltup);
2630 
2631  if (relStruct->relchecks != numchecks)
2632  {
2633  relStruct->relchecks = numchecks;
2634 
2635  CatalogTupleUpdate(relrel, &reltup->t_self, reltup);
2636  }
2637  else
2638  {
2639  /* Skip the disk update, but force relcache inval anyway */
2641  }
2642 
2643  heap_freetuple(reltup);
2644  heap_close(relrel, RowExclusiveLock);
2645 }
2646 
2647 /*
2648  * Take a raw default and convert it to a cooked format ready for
2649  * storage.
2650  *
2651  * Parse state should be set up to recognize any vars that might appear
2652  * in the expression. (Even though we plan to reject vars, it's more
2653  * user-friendly to give the correct error message than "unknown var".)
2654  *
2655  * If atttypid is not InvalidOid, coerce the expression to the specified
2656  * type (and typmod atttypmod). attname is only needed in this case:
2657  * it is used in the error message, if any.
2658  */
2659 Node *
2661  Node *raw_default,
2662  Oid atttypid,
2663  int32 atttypmod,
2664  const char *attname)
2665 {
2666  Node *expr;
2667 
2668  Assert(raw_default != NULL);
2669 
2670  /*
2671  * Transform raw parsetree to executable expression.
2672  */
2673  expr = transformExpr(pstate, raw_default, EXPR_KIND_COLUMN_DEFAULT);
2674 
2675  /*
2676  * Make sure default expr does not refer to any vars (we need this check
2677  * since the pstate includes the target table).
2678  */
2679  if (contain_var_clause(expr))
2680  ereport(ERROR,
2681  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2682  errmsg("cannot use column references in default expression")));
2683 
2684  /*
2685  * transformExpr() should have already rejected subqueries, aggregates,
2686  * window functions, and SRFs, based on the EXPR_KIND_ for a default
2687  * expression.
2688  */
2689 
2690  /*
2691  * Coerce the expression to the correct type and typmod, if given. This
2692  * should match the parser's processing of non-defaulted expressions ---
2693  * see transformAssignedExpr().
2694  */
2695  if (OidIsValid(atttypid))
2696  {
2697  Oid type_id = exprType(expr);
2698 
2699  expr = coerce_to_target_type(pstate, expr, type_id,
2700  atttypid, atttypmod,
2703  -1);
2704  if (expr == NULL)
2705  ereport(ERROR,
2706  (errcode(ERRCODE_DATATYPE_MISMATCH),
2707  errmsg("column \"%s\" is of type %s"
2708  " but default expression is of type %s",
2709  attname,
2710  format_type_be(atttypid),
2711  format_type_be(type_id)),
2712  errhint("You will need to rewrite or cast the expression.")));
2713  }
2714 
2715  /*
2716  * Finally, take care of collations in the finished expression.
2717  */
2718  assign_expr_collations(pstate, expr);
2719 
2720  return expr;
2721 }
2722 
2723 /*
2724  * Take a raw CHECK constraint expression and convert it to a cooked format
2725  * ready for storage.
2726  *
2727  * Parse state must be set up to recognize any vars that might appear
2728  * in the expression.
2729  */
2730 static Node *
2732  Node *raw_constraint,
2733  char *relname)
2734 {
2735  Node *expr;
2736 
2737  /*
2738  * Transform raw parsetree to executable expression.
2739  */
2740  expr = transformExpr(pstate, raw_constraint, EXPR_KIND_CHECK_CONSTRAINT);
2741 
2742  /*
2743  * Make sure it yields a boolean result.
2744  */
2745  expr = coerce_to_boolean(pstate, expr, "CHECK");
2746 
2747  /*
2748  * Take care of collations.
2749  */
2750  assign_expr_collations(pstate, expr);
2751 
2752  /*
2753  * Make sure no outside relations are referred to (this is probably dead
2754  * code now that add_missing_from is history).
2755  */
2756  if (list_length(pstate->p_rtable) != 1)
2757  ereport(ERROR,
2758  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2759  errmsg("only table \"%s\" can be referenced in check constraint",
2760  relname)));
2761 
2762  return expr;
2763 }
2764 
2765 
2766 /*
2767  * RemoveStatistics --- remove entries in pg_statistic for a rel or column
2768  *
2769  * If attnum is zero, remove all entries for rel; else remove only the one(s)
2770  * for that column.
2771  */
2772 void
2774 {
2775  Relation pgstatistic;
2776  SysScanDesc scan;
2777  ScanKeyData key[2];
2778  int nkeys;
2779  HeapTuple tuple;
2780 
2782 
2783  ScanKeyInit(&key[0],
2785  BTEqualStrategyNumber, F_OIDEQ,
2786  ObjectIdGetDatum(relid));
2787 
2788  if (attnum == 0)
2789  nkeys = 1;
2790  else
2791  {
2792  ScanKeyInit(&key[1],
2794  BTEqualStrategyNumber, F_INT2EQ,
2795  Int16GetDatum(attnum));
2796  nkeys = 2;
2797  }
2798 
2799  scan = systable_beginscan(pgstatistic, StatisticRelidAttnumInhIndexId, true,
2800  NULL, nkeys, key);
2801 
2802  /* we must loop even when attnum != 0, in case of inherited stats */
2803  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
2804  CatalogTupleDelete(pgstatistic, &tuple->t_self);
2805 
2806  systable_endscan(scan);
2807 
2808  heap_close(pgstatistic, RowExclusiveLock);
2809 }
2810 
2811 
2812 /*
2813  * RelationTruncateIndexes - truncate all indexes associated
2814  * with the heap relation to zero tuples.
2815  *
2816  * The routine will truncate and then reconstruct the indexes on
2817  * the specified relation. Caller must hold exclusive lock on rel.
2818  */
2819 static void
2821 {
2822  ListCell *indlist;
2823 
2824  /* Ask the relcache to produce a list of the indexes of the rel */
2825  foreach(indlist, RelationGetIndexList(heapRelation))
2826  {
2827  Oid indexId = lfirst_oid(indlist);
2828  Relation currentIndex;
2829  IndexInfo *indexInfo;
2830 
2831  /* Open the index relation; use exclusive lock, just to be sure */
2832  currentIndex = index_open(indexId, AccessExclusiveLock);
2833 
2834  /* Fetch info needed for index_build */
2835  indexInfo = BuildIndexInfo(currentIndex);
2836 
2837  /*
2838  * Now truncate the actual file (and discard buffers).
2839  */
2840  RelationTruncate(currentIndex, 0);
2841 
2842  /* Initialize the index and rebuild */
2843  /* Note: we do not need to re-establish pkey setting */
2844  index_build(heapRelation, currentIndex, indexInfo, false, true);
2845 
2846  /* We're done with this index */
2847  index_close(currentIndex, NoLock);
2848  }
2849 }
2850 
2851 /*
2852  * heap_truncate
2853  *
2854  * This routine deletes all data within all the specified relations.
2855  *
2856  * This is not transaction-safe! There is another, transaction-safe
2857  * implementation in commands/tablecmds.c. We now use this only for
2858  * ON COMMIT truncation of temporary tables, where it doesn't matter.
2859  */
2860 void
2862 {
2863  List *relations = NIL;
2864  ListCell *cell;
2865 
2866  /* Open relations for processing, and grab exclusive access on each */
2867  foreach(cell, relids)
2868  {
2869  Oid rid = lfirst_oid(cell);
2870  Relation rel;
2871 
2872  rel = heap_open(rid, AccessExclusiveLock);
2873  relations = lappend(relations, rel);
2874  }
2875 
2876  /* Don't allow truncate on tables that are referenced by foreign keys */
2877  heap_truncate_check_FKs(relations, true);
2878 
2879  /* OK to do it */
2880  foreach(cell, relations)
2881  {
2882  Relation rel = lfirst(cell);
2883 
2884  /* Truncate the relation */
2885  heap_truncate_one_rel(rel);
2886 
2887  /* Close the relation, but keep exclusive lock on it until commit */
2888  heap_close(rel, NoLock);
2889  }
2890 }
2891 
2892 /*
2893  * heap_truncate_one_rel
2894  *
2895  * This routine deletes all data within the specified relation.
2896  *
2897  * This is not transaction-safe, because the truncation is done immediately
2898  * and cannot be rolled back later. Caller is responsible for having
2899  * checked permissions etc, and must have obtained AccessExclusiveLock.
2900  */
2901 void
2903 {
2904  Oid toastrelid;
2905 
2906  /* Truncate the actual file (and discard buffers) */
2907  RelationTruncate(rel, 0);
2908 
2909  /* If the relation has indexes, truncate the indexes too */
2911 
2912  /* If there is a toast table, truncate that too */
2913  toastrelid = rel->rd_rel->reltoastrelid;
2914  if (OidIsValid(toastrelid))
2915  {
2916  Relation toastrel = heap_open(toastrelid, AccessExclusiveLock);
2917 
2918  RelationTruncate(toastrel, 0);
2919  RelationTruncateIndexes(toastrel);
2920  /* keep the lock... */
2921  heap_close(toastrel, NoLock);
2922  }
2923 }
2924 
2925 /*
2926  * heap_truncate_check_FKs
2927  * Check for foreign keys referencing a list of relations that
2928  * are to be truncated, and raise error if there are any
2929  *
2930  * We disallow such FKs (except self-referential ones) since the whole point
2931  * of TRUNCATE is to not scan the individual rows to be thrown away.
2932  *
2933  * This is split out so it can be shared by both implementations of truncate.
2934  * Caller should already hold a suitable lock on the relations.
2935  *
2936  * tempTables is only used to select an appropriate error message.
2937  */
2938 void
2939 heap_truncate_check_FKs(List *relations, bool tempTables)
2940 {
2941  List *oids = NIL;
2942  List *dependents;
2943  ListCell *cell;
2944 
2945  /*
2946  * Build a list of OIDs of the interesting relations.
2947  *
2948  * If a relation has no triggers, then it can neither have FKs nor be
2949  * referenced by a FK from another table, so we can ignore it.
2950  */
2951  foreach(cell, relations)
2952  {
2953  Relation rel = lfirst(cell);
2954 
2955  if (rel->rd_rel->relhastriggers)
2956  oids = lappend_oid(oids, RelationGetRelid(rel));
2957  }
2958 
2959  /*
2960  * Fast path: if no relation has triggers, none has FKs either.
2961  */
2962  if (oids == NIL)
2963  return;
2964 
2965  /*
2966  * Otherwise, must scan pg_constraint. We make one pass with all the
2967  * relations considered; if this finds nothing, then all is well.
2968  */
2969  dependents = heap_truncate_find_FKs(oids);
2970  if (dependents == NIL)
2971  return;
2972 
2973  /*
2974  * Otherwise we repeat the scan once per relation to identify a particular
2975  * pair of relations to complain about. This is pretty slow, but
2976  * performance shouldn't matter much in a failure path. The reason for
2977  * doing things this way is to ensure that the message produced is not
2978  * dependent on chance row locations within pg_constraint.
2979  */
2980  foreach(cell, oids)
2981  {
2982  Oid relid = lfirst_oid(cell);
2983  ListCell *cell2;
2984 
2985  dependents = heap_truncate_find_FKs(list_make1_oid(relid));
2986 
2987  foreach(cell2, dependents)
2988  {
2989  Oid relid2 = lfirst_oid(cell2);
2990 
2991  if (!list_member_oid(oids, relid2))
2992  {
2993  char *relname = get_rel_name(relid);
2994  char *relname2 = get_rel_name(relid2);
2995 
2996  if (tempTables)
2997  ereport(ERROR,
2998  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2999  errmsg("unsupported ON COMMIT and foreign key combination"),
3000  errdetail("Table \"%s\" references \"%s\", but they do not have the same ON COMMIT setting.",
3001  relname2, relname)));
3002  else
3003  ereport(ERROR,
3004  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3005  errmsg("cannot truncate a table referenced in a foreign key constraint"),
3006  errdetail("Table \"%s\" references \"%s\".",
3007  relname2, relname),
3008  errhint("Truncate table \"%s\" at the same time, "
3009  "or use TRUNCATE ... CASCADE.",
3010  relname2)));
3011  }
3012  }
3013  }
3014 }
3015 
3016 /*
3017  * heap_truncate_find_FKs
3018  * Find relations having foreign keys referencing any of the given rels
3019  *
3020  * Input and result are both lists of relation OIDs. The result contains
3021  * no duplicates, does *not* include any rels that were already in the input
3022  * list, and is sorted in OID order. (The last property is enforced mainly
3023  * to guarantee consistent behavior in the regression tests; we don't want
3024  * behavior to change depending on chance locations of rows in pg_constraint.)
3025  *
3026  * Note: caller should already have appropriate lock on all rels mentioned
3027  * in relationIds. Since adding or dropping an FK requires exclusive lock
3028  * on both rels, this ensures that the answer will be stable.
3029  */
3030 List *
3032 {
3033  List *result = NIL;
3034  Relation fkeyRel;
3035  SysScanDesc fkeyScan;
3036  HeapTuple tuple;
3037 
3038  /*
3039  * Must scan pg_constraint. Right now, it is a seqscan because there is
3040  * no available index on confrelid.
3041  */
3043 
3044  fkeyScan = systable_beginscan(fkeyRel, InvalidOid, false,
3045  NULL, 0, NULL);
3046 
3047  while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
3048  {
3050 
3051  /* Not a foreign key */
3052  if (con->contype != CONSTRAINT_FOREIGN)
3053  continue;
3054 
3055  /* Not referencing one of our list of tables */
3056  if (!list_member_oid(relationIds, con->confrelid))
3057  continue;
3058 
3059  /* Add referencer unless already in input or result list */
3060  if (!list_member_oid(relationIds, con->conrelid))
3061  result = insert_ordered_unique_oid(result, con->conrelid);
3062  }
3063 
3064  systable_endscan(fkeyScan);
3065  heap_close(fkeyRel, AccessShareLock);
3066 
3067  return result;
3068 }
3069 
3070 /*
3071  * insert_ordered_unique_oid
3072  * Insert a new Oid into a sorted list of Oids, preserving ordering,
3073  * and eliminating duplicates
3074  *
3075  * Building the ordered list this way is O(N^2), but with a pretty small
3076  * constant, so for the number of entries we expect it will probably be
3077  * faster than trying to apply qsort(). It seems unlikely someone would be
3078  * trying to truncate a table with thousands of dependent tables ...
3079  */
3080 static List *
3082 {
3083  ListCell *prev;
3084 
3085  /* Does the datum belong at the front? */
3086  if (list == NIL || datum < linitial_oid(list))
3087  return lcons_oid(datum, list);
3088  /* Does it match the first entry? */
3089  if (datum == linitial_oid(list))
3090  return list; /* duplicate, so don't insert */
3091  /* No, so find the entry it belongs after */
3092  prev = list_head(list);
3093  for (;;)
3094  {
3095  ListCell *curr = lnext(prev);
3096 
3097  if (curr == NULL || datum < lfirst_oid(curr))
3098  break; /* it belongs after 'prev', before 'curr' */
3099 
3100  if (datum == lfirst_oid(curr))
3101  return list; /* duplicate, so don't insert */
3102 
3103  prev = curr;
3104  }
3105  /* Insert datum into list after 'prev' */
3106  lappend_cell_oid(list, prev, datum);
3107  return list;
3108 }
3109 
3110 /*
3111  * StorePartitionKey
3112  * Store information about the partition key rel into the catalog
3113  */
3114 void
3116  char strategy,
3117  int16 partnatts,
3118  AttrNumber *partattrs,
3119  List *partexprs,
3120  Oid *partopclass,
3121  Oid *partcollation)
3122 {
3123  int i;
3124  int2vector *partattrs_vec;
3125  oidvector *partopclass_vec;
3126  oidvector *partcollation_vec;
3127  Datum partexprDatum;
3128  Relation pg_partitioned_table;
3129  HeapTuple tuple;
3131  bool nulls[Natts_pg_partitioned_table];
3132  ObjectAddress myself;
3133  ObjectAddress referenced;
3134 
3135  Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
3136 
3137  /* Copy the partition attribute numbers, opclass OIDs into arrays */
3138  partattrs_vec = buildint2vector(partattrs, partnatts);
3139  partopclass_vec = buildoidvector(partopclass, partnatts);
3140  partcollation_vec = buildoidvector(partcollation, partnatts);
3141 
3142  /* Convert the expressions (if any) to a text datum */
3143  if (partexprs)
3144  {
3145  char *exprString;
3146 
3147  exprString = nodeToString(partexprs);
3148  partexprDatum = CStringGetTextDatum(exprString);
3149  pfree(exprString);
3150  }
3151  else
3152  partexprDatum = (Datum) 0;
3153 
3154  pg_partitioned_table = heap_open(PartitionedRelationId, RowExclusiveLock);
3155 
3156  MemSet(nulls, false, sizeof(nulls));
3157 
3158  /* Only this can ever be NULL */
3159  if (!partexprDatum)
3160  nulls[Anum_pg_partitioned_table_partexprs - 1] = true;
3161 
3163  values[Anum_pg_partitioned_table_partstrat - 1] = CharGetDatum(strategy);
3164  values[Anum_pg_partitioned_table_partnatts - 1] = Int16GetDatum(partnatts);
3166  values[Anum_pg_partitioned_table_partattrs - 1] = PointerGetDatum(partattrs_vec);
3167  values[Anum_pg_partitioned_table_partclass - 1] = PointerGetDatum(partopclass_vec);
3168  values[Anum_pg_partitioned_table_partcollation - 1] = PointerGetDatum(partcollation_vec);
3169  values[Anum_pg_partitioned_table_partexprs - 1] = partexprDatum;
3170 
3171  tuple = heap_form_tuple(RelationGetDescr(pg_partitioned_table), values, nulls);
3172 
3173  CatalogTupleInsert(pg_partitioned_table, tuple);
3174  heap_close(pg_partitioned_table, RowExclusiveLock);
3175 
3176  /* Mark this relation as dependent on a few things as follows */
3177  myself.classId = RelationRelationId;
3178  myself.objectId = RelationGetRelid(rel);;
3179  myself.objectSubId = 0;
3180 
3181  /* Operator class and collation per key column */
3182  for (i = 0; i < partnatts; i++)
3183  {
3184  referenced.classId = OperatorClassRelationId;
3185  referenced.objectId = partopclass[i];
3186  referenced.objectSubId = 0;
3187 
3188  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3189 
3190  /* The default collation is pinned, so don't bother recording it */
3191  if (OidIsValid(partcollation[i]) &&
3192  partcollation[i] != DEFAULT_COLLATION_OID)
3193  {
3194  referenced.classId = CollationRelationId;
3195  referenced.objectId = partcollation[i];
3196  referenced.objectSubId = 0;
3197  }
3198 
3199  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
3200  }
3201 
3202  /*
3203  * Anything mentioned in the expressions. We must ignore the column
3204  * references, which will depend on the table itself; there is no separate
3205  * partition key object.
3206  */
3207  if (partexprs)
3209  (Node *) partexprs,
3210  RelationGetRelid(rel),
3212  DEPENDENCY_AUTO, true);
3213 
3214  /*
3215  * We must invalidate the relcache so that the next
3216  * CommandCounterIncrement() will cause the same to be rebuilt using the
3217  * information in just created catalog entry.
3218  */
3220 }
3221 
3222 /*
3223  * RemovePartitionKeyByRelId
3224  * Remove pg_partitioned_table entry for a relation
3225  */
3226 void
3228 {
3229  Relation rel;
3230  HeapTuple tuple;
3231 
3233 
3234  tuple = SearchSysCache1(PARTRELID, ObjectIdGetDatum(relid));
3235  if (!HeapTupleIsValid(tuple))
3236  elog(ERROR, "cache lookup failed for partition key of relation %u",
3237  relid);
3238 
3239  CatalogTupleDelete(rel, &tuple->t_self);
3240 
3241  ReleaseSysCache(tuple);
3243 }
3244 
3245 /*
3246  * StorePartitionBound
3247  * Update pg_class tuple of rel to store the partition bound and set
3248  * relispartition to true
3249  *
3250  * Also, invalidate the parent's relcache, so that the next rebuild will load
3251  * the new partition's info into its partition descriptor.  If there is a
3252  * default partition, we must invalidate its relcache entry as well.
3253  */
3254 void
3256 {
3257  Relation classRel;
3258  HeapTuple tuple,
3259  newtuple;
3260  Datum new_val[Natts_pg_class];
3261  bool new_null[Natts_pg_class],
3262  new_repl[Natts_pg_class];
3263  Oid defaultPartOid;
3264 
3265  /* Update pg_class tuple */
3267  tuple = SearchSysCacheCopy1(RELOID,
3269  if (!HeapTupleIsValid(tuple))
3270  elog(ERROR, "cache lookup failed for relation %u",
3271  RelationGetRelid(rel));
3272 
3273 #ifdef USE_ASSERT_CHECKING
3274  {
3275  Form_pg_class classForm;
3276  bool isnull;
3277 
3278  classForm = (Form_pg_class) GETSTRUCT(tuple);
3279  Assert(!classForm->relispartition);
3281  &isnull);
3282  Assert(isnull);
3283  }
3284 #endif
3285 
3286  /* Fill in relpartbound value */
3287  memset(new_val, 0, sizeof(new_val));
3288  memset(new_null, false, sizeof(new_null));
3289  memset(new_repl, false, sizeof(new_repl));
3291  new_null[Anum_pg_class_relpartbound - 1] = false;
3292  new_repl[Anum_pg_class_relpartbound - 1] = true;
3293  newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
3294  new_val, new_null, new_repl);
3295  /* Also set the flag */
3296  ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = true;
3297  CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
3298  heap_freetuple(newtuple);
3299  heap_close(classRel, RowExclusiveLock);
3300 
3301  /*
3302  * The partition constraint for the default partition depends on the
3303  * partition bounds of every other partition, so we must invalidate the
3304  * relcache entry for that partition every time a partition is added or
3305  * removed.
3306  */
3307  defaultPartOid = get_default_oid_from_partdesc(RelationGetPartitionDesc(parent));
3308  if (OidIsValid(defaultPartOid))
3309  CacheInvalidateRelcacheByRelid(defaultPartOid);
3310 
3311  CacheInvalidateRelcache(parent);
3312 }
#define Natts_pg_class
Definition: pg_class.h:102
signed short int16
Definition: c.h:293
#define AttributeRelidNumIndexId
Definition: indexing.h:94
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
#define NIL
Definition: pg_list.h:69
uint32 CommandId
Definition: c.h:469
Definition: c.h:536
static const Form_pg_attribute SysAtt[]
Definition: heap.c:192
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:421
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
char * ChooseConstraintName(const char *name1, const char *name2, const char *label, Oid namespaceid, List *others)
#define Anum_pg_attribute_attrelid
Definition: pg_attribute.h:195
#define Anum_pg_attribute_attinhcount
Definition: pg_attribute.h:212
#define Anum_pg_class_relhasindex
Definition: pg_class.h:115
#define Anum_pg_inherits_inhrelid
Definition: pg_inherits.h:50
#define CONSTRAINT_FOREIGN
#define Anum_pg_attribute_atttypid
Definition: pg_attribute.h:197
#define Anum_pg_class_relpersistence
Definition: pg_class.h:117
#define NamespaceRelationId
Definition: pg_namespace.h:34
#define Anum_pg_attribute_attlen
Definition: pg_attribute.h:199
void * stringToNode(char *str)
Definition: read.c:38
void register_on_commit_action(Oid relid, OnCommitAction action)
Definition: tablecmds.c:12928
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
#define NameGetDatum(X)
Definition: postgres.h:601
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:767
static void SetRelationNumChecks(Relation rel, int numchecks)
Definition: heap.c:2617
Oid tdtypeid
Definition: tupdesc.h:80
int errhint(const char *fmt,...)
Definition: elog.c:987
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:3154
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:376
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
bool is_no_inherit
Definition: heap.h:38
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:724
#define Anum_pg_class_relacl
Definition: pg_class.h:133
bool tdhasoid
Definition: tupdesc.h:82
#define MultiXactIdGetDatum(X)
Definition: postgres.h:534
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:172
void RemoveSubscriptionRel(Oid subid, Oid relid)
void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, bool allow_system_table_mods)
Definition: heap.c:411
#define Anum_pg_attribute_attbyval
Definition: pg_attribute.h:204
void StorePartitionKey(Relation rel, char strategy, int16 partnatts, AttrNumber *partattrs, List *partexprs, Oid *partopclass, Oid *partcollation)
Definition: heap.c:3115
Oid binary_upgrade_next_heap_pg_class_oid
Definition: heap.c:86
AttrNumber attnum
Definition: heap.h:24
uint32 TransactionId
Definition: c.h:455
#define TYPTYPE_BASE
Definition: pg_type.h:720
#define Anum_pg_attribute_attnum
Definition: pg_attribute.h:200
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2986
#define RelationGetDescr(relation)
Definition: rel.h:437
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define Anum_pg_partitioned_table_partexprs
Oid binary_upgrade_next_toast_pg_class_oid
Definition: heap.c:87
#define TYPTYPE_COMPOSITE
Definition: pg_type.h:721
#define OIDOID
Definition: pg_type.h:328
#define Anum_pg_class_relispartition
Definition: pg_class.h:130
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2517
#define PointerGetDatum(X)
Definition: postgres.h:562
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define Anum_pg_class_reloptions
Definition: pg_class.h:134
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
Node * raw_expr
Definition: parsenodes.h:2083
#define RelationRelationId
Definition: pg_class.h:29
static Node * cookConstraint(ParseState *pstate, Node *raw_constraint, char *relname)
Definition: heap.c:2731
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:110
void heap_truncate_one_rel(Relation rel)
Definition: heap.c:2902
#define Anum_pg_class_reltablespace
Definition: pg_class.h:110
#define Anum_pg_attribute_atthasdef
Definition: pg_attribute.h:208
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:146
#define RELKIND_MATVIEW
Definition: pg_class.h:165
#define Int16GetDatum(X)
Definition: postgres.h:457
void update_default_partition_oid(Oid parentId, Oid defaultPartId)
Definition: partition.c:3028
Form_pg_attribute SystemAttributeByName(const char *attname, bool relhasoids)
Definition: heap.c:214
#define AccessShareLock
Definition: lockdefs.h:36
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define Anum_pg_attribute_attndims
Definition: pg_attribute.h:201
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
Definition: nodes.h:512
static FormData_pg_attribute a3
Definition: heap.c:156
#define AttrDefaultOidIndexId
Definition: indexing.h:89
#define AttributeRelationId
Definition: pg_attribute.h:33
void remove_on_commit_action(Oid relid)
Definition: tablecmds.c:12959
int errcode(int sqlerrcode)
Definition: elog.c:575
TransactionId RecentXmin
Definition: snapmgr.c:165
#define Anum_pg_attribute_attacl
Definition: pg_attribute.h:214
void heap_truncate_check_FKs(List *relations, bool tempTables)
Definition: heap.c:2939
#define Anum_pg_attrdef_adbin
Definition: pg_attrdef.h:56
char get_typtype(Oid typid)
Definition: lsyscache.c:2398
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1266
#define MemSet(start, val, len)
Definition: c.h:877
AttrNumber varattno
Definition: primnodes.h:168
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
#define Anum_pg_statistic_staattnum
Definition: pg_statistic.h:137
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void RelationForgetRelation(Oid rid)
Definition: relcache.c:2655
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
#define XIDOID
Definition: pg_type.h:336
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
List * lcons_oid(Oid datum, List *list)
Definition: list.c:295
#define heap_close(r, l)
Definition: heapam.h:97
List * list_union(const List *list1, const List *list2)
Definition: list.c:697
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:1699
bool contain_var_clause(Node *node)
Definition: var.c:331
char * conname
Definition: parsenodes.h:2076
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:159
#define lengthof(array)
Definition: c.h:610
#define MinCommandIdAttributeNumber
Definition: sysattr.h:24
#define Anum_pg_constraint_conname
static FormData_pg_attribute a7
Definition: heap.c:186
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:177
Form_pg_class rd_rel
Definition: rel.h:114
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:163
#define TypeRelationId
Definition: pg_type.h:34
int namestrcpy(Name name, const char *str)
Definition: name.c:216
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:586
#define Anum_pg_constraint_conbin
#define Anum_pg_class_relispopulated
Definition: pg_class.h:128
#define Anum_pg_class_relnatts
Definition: pg_class.h:119
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
int natts
Definition: tupdesc.h:79
bool IsBinaryUpgrade
Definition: globals.c:102
#define Anum_pg_class_relnamespace
Definition: pg_class.h:104
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
OnCommitAction
Definition: primnodes.h:47
#define Anum_pg_class_relfilenode
Definition: pg_class.h:109
signed int int32
Definition: c.h:294
Oid MyDatabaseTableSpace
Definition: globals.c:79
#define Anum_pg_partitioned_table_partrelid
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
char * get_attname(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:774
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
#define Anum_pg_attribute_attislocal
Definition: pg_attribute.h:211
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:703
#define Anum_pg_class_relhasrules
Definition: pg_class.h:123
Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, const char *attname)
Definition: heap.c:2660
#define NAMEDATALEN
#define Anum_pg_class_relkind
Definition: pg_class.h:118
void assign_expr_collations(ParseState *pstate, Node *expr)
#define Anum_pg_class_relhasoids
Definition: pg_class.h:121
#define Anum_pg_attribute_attisdropped
Definition: pg_attribute.h:210
#define CONSTRAINT_CHECK
void InsertPgClassTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Datum relacl, Datum reloptions)
Definition: heap.c:767
#define RelationOpenSmgr(relation)
Definition: rel.h:469
#define TIDOID
Definition: pg_type.h:332
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
Oid get_typ_typrelid(Oid typid)
Definition: lsyscache.c:2490
void pfree(void *pointer)
Definition: mcxt.c:936
AttrNumber attnum
Definition: heap.h:33
#define linitial(l)
Definition: pg_list.h:111
#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
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define Anum_pg_class_reltype
Definition: pg_class.h:105
#define Anum_pg_attribute_attstattarget
Definition: pg_attribute.h:198
#define Anum_pg_attribute_atttypmod
Definition: pg_attribute.h:203
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:78
#define Anum_pg_class_reloftype
Definition: pg_class.h:106
Oid get_partition_parent(Oid relid)
Definition: partition.c:1372
Datum Float4GetDatum(float4 X)
Definition: fmgr.c:1798
#define AttrDefaultIndexId
Definition: indexing.h:87
ItemPointerData t_self
Definition: htup.h:65
#define TYPCATEGORY_ARRAY
Definition: pg_type.h:728
const ObjectAddress * object
Definition: dependency.c:122
Oid get_relname_relid(const char *relname, Oid relnamespace)
Definition: lsyscache.c:1702
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
int inhcount
Definition: heap.h:37
ListCell * lappend_cell_oid(List *list, ListCell *prev, Oid datum)
Definition: list.c:235
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3066
#define Anum_pg_partitioned_table_partcollation
#define NoLock
Definition: lockdefs.h:34
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:833
#define IsNormalProcessingMode()
Definition: miscadmin.h:369
#define Anum_pg_class_relname
Definition: pg_class.h:103
void heap_create_init_fork(Relation rel)
Definition: heap.c:1383
#define PartitionedRelationId
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75
bool IsUnderPostmaster
Definition: globals.c:101
#define RowExclusiveLock
Definition: lockdefs.h:38
List * deparse_context_for(const char *aliasname, Oid relid)
Definition: ruleutils.c:3070
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define Anum_pg_partitioned_table_partdefid
#define CStringGetDatum(X)
Definition: postgres.h:584
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1363
void RemoveAttributeById(Oid relid, AttrNumber attnum)
Definition: heap.c:1544
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:303
static ObjectAddress AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, char new_rel_kind, Oid ownerid, Oid new_row_type, Oid new_array_type)
Definition: heap.c:945
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition: inval.c:1292
#define InvalidTransactionId
Definition: transam.h:31
static void StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
Definition: heap.c:2160
#define RelationGetRelationName(relation)
Definition: rel.h:445
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
Node * raw_default
Definition: heap.h:25
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define TableOidAttributeNumber
Definition: sysattr.h:27
#define Anum_pg_class_relpages
Definition: pg_class.h:111
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:167
bool skip_validation
Definition: heap.h:35
#define Anum_pg_partitioned_table_partnatts
#define Anum_pg_class_relminmxid
Definition: pg_class.h:132
ConstrType contype
Definition: heap.h:30
void CheckTableNotInUse(Relation rel, const char *stmt)
Definition: tablecmds.c:3112
#define Anum_pg_statistic_starelid
Definition: pg_statistic.h:136
#define lnext(lc)
Definition: pg_list.h:105
void RemoveAttrDefaultById(Oid attrdefId)
Definition: heap.c:1686
#define ereport(elevel, rest)
Definition: elog.h:122
static void AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc, char relkind, bool oidislocal, int oidinhcount)
Definition: heap.c:657
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Oid get_default_partition_oid(Oid parentId)
Definition: partition.c:3003
#define MaxCommandIdAttributeNumber
Definition: sysattr.h:26
#define MaxTransactionIdAttributeNumber
Definition: sysattr.h:25
List * lappend(List *list, void *datum)
Definition: list.c:128
#define RELKIND_PARTITIONED_INDEX
Definition: pg_class.h:169
void CheckAttributeType(const char *attname, Oid atttypid, Oid attcollation, List *containing_rowtypes, bool allow_system_table_mods)
Definition: heap.c:491
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isprimary, bool isreindex)
Definition: index.c:2176
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define Anum_pg_attribute_attcacheoff
Definition: pg_attribute.h:202
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
#define Anum_pg_class_relreplident
Definition: pg_class.h:129
Definition: c.h:525
#define TextDatumGetCString(d)
Definition: builtins.h:92
#define TransactionIdGetDatum(X)
Definition: postgres.h:527
MultiXactId GetOldestMultiXactId(void)
Definition: multixact.c:2491
DropBehavior
Definition: parsenodes.h:1686
#define Anum_pg_class_relhassubclass
Definition: pg_class.h:125
#define ANYARRAYOID
Definition: pg_type.h:688
static FormData_pg_attribute a4
Definition: heap.c:162
#define TYPCATEGORY_COMPOSITE
Definition: pg_type.h:730
#define CIDOID
Definition: pg_type.h:340
#define RELKIND_TOASTVALUE
Definition: pg_class.h:163
#define Anum_pg_attribute_attidentity
Definition: pg_attribute.h:209
void RelationDropStorage(Relation rel)
Definition: storage.c:145
#define Anum_pg_class_relisshared
Definition: pg_class.h:116
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:915
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define StatisticRelationId
Definition: pg_statistic.h:29
#define Anum_pg_attrdef_adsrc
Definition: pg_attrdef.h:57
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
#define list_make1_oid(x1)
Definition: pg_list.h:151
#define Anum_pg_class_reltuples
Definition: pg_class.h:112
#define Anum_pg_attribute_attalign
Definition: pg_attribute.h:206
#define Anum_pg_constraint_connamespace
static bool MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr, bool allow_merge, bool is_local, bool is_initially_valid, bool is_no_inherit)
Definition: heap.c:2467
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define InvalidMultiXactId
Definition: multixact.h:23
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:147
#define CollationRelationId
Definition: pg_collation.h:30
TupleDesc rd_att
Definition: rel.h:115
#define BoolGetDatum(X)
Definition: postgres.h:408
static FormData_pg_attribute a6
Definition: heap.c:174
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:163
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:200
#define InvalidOid
Definition: postgres_ext.h:36
void StorePartitionBound(Relation rel, Relation parent, PartitionBoundSpec *bound)
Definition: heap.c:3255
FormData_pg_attribute
Definition: pg_attribute.h:171
#define Anum_pg_attrdef_adrelid
Definition: pg_attrdef.h:54
bool is_no_inherit
Definition: parsenodes.h:2082
bool initially_valid
Definition: parsenodes.h:2114
void DeleteRelationTuple(Oid relid)
Definition: heap.c:1437
RelFileNode node
Definition: relfilenode.h:74
#define NOTICE
Definition: elog.h:37
#define ConstraintNameNspIndexId
Definition: indexing.h:124
static FormData_pg_attribute a1
Definition: heap.c:144
#define Anum_pg_class_relpartbound
Definition: pg_class.h:135
#define Anum_pg_partitioned_table_partstrat
#define MaxHeapAttributeNumber
Definition: htup_details.h:47
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
RelFileNode rd_node
Definition: rel.h:85
#define Anum_pg_attrdef_adnum
Definition: pg_attrdef.h:55
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
int aclmembers(const Acl *acl, Oid **roleids)
Definition: acl.c:1473
#define Anum_pg_attribute_attnotnull
Definition: pg_attribute.h:207
#define Assert(condition)
Definition: c.h:680
oidvector * buildoidvector(const Oid *oids, int n)
Definition: oid.c:167
#define lfirst(lc)
Definition: pg_list.h:106
#define Natts_pg_partitioned_table
static void RelationRemoveInheritance(Oid relid)
Definition: heap.c:1404
#define StatisticRelidAttnumInhIndexId
Definition: indexing.h:234
#define Anum_pg_class_relhaspkey
Definition: pg_class.h:122
#define Anum_pg_class_relallvisible
Definition: pg_class.h:113
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139
CatalogIndexState CatalogOpenIndexes(Relation heapRel)
Definition: indexing.c:40
struct ItemPointerData ItemPointerData
char * deparse_expression(Node *expr, List *dpcontext, bool forceprefix, bool showimplicit)
Definition: ruleutils.c:3011
TupleConstr * constr
Definition: tupdesc.h:84
#define linitial_oid(l)
Definition: pg_list.h:113
static List * insert_ordered_unique_oid(List *list, Oid datum)
Definition: heap.c:3081
#define InheritsRelidSeqnoIndexId
Definition: indexing.h:167
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
void heap_truncate(List *relids)
Definition: heap.c:2861
static int list_length(const List *l)
Definition: pg_list.h:89
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:395
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, Alias *alias, bool inh, bool inFromCl)
void CheckTableForSerializableConflictIn(Relation relation)
Definition: predicate.c:4410
void DeleteAttributeTuples(Oid relid)
Definition: heap.c:1466
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4324
#define Anum_pg_class_reltoastrelid
Definition: pg_class.h:114
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool ignore_self)
Definition: dependency.c:1404
#define Anum_pg_attribute_attfdwoptions
Definition: pg_attribute.h:216
Oid AssignTypeArrayOid(void)
Definition: typecmds.c:2099
#define CharGetDatum(X)
Definition: postgres.h:422
#define TYPTYPE_PSEUDO
Definition: pg_type.h:724
#define InheritsRelationId
Definition: pg_inherits.h:29
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
static void AddNewRelationTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, Oid reloftype, Oid relowner, char relkind, Datum relacl, Datum reloptions)
Definition: heap.c:846
#define DatumGetPointer(X)
Definition: postgres.h:555
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1233
void RemoveStatistics(Oid relid, AttrNumber attnum)
Definition: heap.c:2773
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:367
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#define AccessExclusiveLock
Definition: lockdefs.h:45
#define Int32GetDatum(X)
Definition: postgres.h:485
void InsertPgAttributeTuple(Relation pg_attribute_rel, Form_pg_attribute new_attribute, CatalogIndexState indstate)
Definition: heap.c:601
#define Anum_pg_attribute_attoptions
Definition: pg_attribute.h:215
void RemovePartitionKeyByRelId(Oid relid)
Definition: heap.c:3227
void * palloc(Size size)
Definition: mcxt.c:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define Anum_pg_class_relforcerowsecurity
Definition: pg_class.h:127
#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 ForeignTableRelationId
void DeleteSystemAttributeTuples(Oid relid)
Definition: heap.c:1503
int i
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: heap.c:1022
Oid conoid
Definition: heap.h:31
#define NameStr(name)
Definition: c.h:557
#define RELKIND_INDEX
Definition: pg_class.h:161
void log_smgrcreate(RelFileNode *rnode, ForkNumber forkNum)
Definition: storage.c:125
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define CStringGetTextDatum(s)
Definition: builtins.h:91
char * nodeToString(const void *obj)
Definition: outfuncs.c:4270
ConstrType contype
Definition: parsenodes.h:2073
#define Anum_pg_class_relam
Definition: pg_class.h:108
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1120
void CatalogCloseIndexes(CatalogIndexState indstate)
Definition: indexing.c:58
Node * expr
Definition: heap.h:34
#define Anum_pg_class_relfrozenxid
Definition: pg_class.h:131
uint16 num_check
Definition: tupdesc.h:42
#define Natts_pg_attribute
Definition: pg_attribute.h:194
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define Anum_pg_attribute_attcollation
Definition: pg_attribute.h:213
void RemoveAttrDefault(Oid relid, AttrNumber attnum, DropBehavior behavior, bool complain, bool internal)
Definition: heap.c:1632
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
#define elog
Definition: elog.h:219
char * cooked_expr
Definition: parsenodes.h:2084
#define Anum_pg_partitioned_table_partclass
Oid CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup, CatalogIndexState indstate)
Definition: indexing.c:186
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
#define Anum_pg_attribute_attstorage
Definition: pg_attribute.h:205
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
#define Anum_pg_class_relhastriggers
Definition: pg_class.h:124
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal)
Definition: heap.c:1930
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:175
#define AttrDefaultRelationId
Definition: pg_attrdef.h:29
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2290
#define RELKIND_RELATION
Definition: pg_class.h:160
void heap_drop_with_catalog(Oid relid)
Definition: heap.c:1759
#define MinTransactionIdAttributeNumber
Definition: sysattr.h:23
#define Anum_pg_partitioned_table_partattrs
bool type_is_collatable(Oid typid)
Definition: lsyscache.c:2839
Definition: regcomp.c:224
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1745
#define Anum_pg_class_relchecks
Definition: pg_class.h:120
void smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:734
int16 AttrNumber
Definition: attnum.h:21
bool skip_validation
Definition: parsenodes.h:2113
void RelationCreateStorage(RelFileNode rnode, char relpersistence)
Definition: storage.c:78
char * name
Definition: heap.h:32
static FormData_pg_attribute a5
Definition: heap.c:168
#define RelationGetRelid(relation)
Definition: rel.h:425
#define Anum_pg_class_relrowsecurity
Definition: pg_class.h:126
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid relId, const int16 *constraintKey, int constraintNKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, const char *conSrc, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
Definition: pg_constraint.c:49
Oid get_default_oid_from_partdesc(PartitionDesc partdesc)
Definition: partition.c:2986
long val
Definition: informix.c:689
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
List * AddRelationNewConstraints(Relation rel, List *newColDefaults, List *newConstraints, bool allow_merge, bool is_local, bool is_internal)
Definition: heap.c:2230
#define BTEqualStrategyNumber
Definition: stratnum.h:31
static Oid StoreRelCheck(Relation rel, const char *ccname, Node *expr, bool is_validated, bool is_local, int inhcount, bool is_no_inherit, bool is_internal)
Definition: heap.c:2043
#define Anum_pg_attribute_attname
Definition: pg_attribute.h:196
List * heap_truncate_find_FKs(List *relationIds)
Definition: heap.c:3031
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:5452
#define lfirst_oid(lc)
Definition: pg_list.h:108
List * list_delete_first(List *list)
Definition: list.c:666
#define RelationGetPartitionDesc(relation)
Definition: rel.h:641
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:189
static void RelationTruncateIndexes(Relation heapRelation)
Definition: heap.c:2820
bool is_local
Definition: heap.h:36
#define Anum_pg_class_relowner
Definition: pg_class.h:107
static FormData_pg_attribute a2
Definition: heap.c:150
void RelationTruncate(Relation rel, BlockNumber nblocks)
Definition: storage.c:227
#define RelationGetNamespace(relation)
Definition: rel.h:452
List * p_rtable
Definition: parse_node.h:173
Node * coerce_to_boolean(ParseState *pstate, Node *node, const char *constructName)