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