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