PostgreSQL Source Code  git master
tablecmds.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * tablecmds.c
4  * Commands for creating and altering table structures and settings
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/commands/tablecmds.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/attmap.h"
18 #include "access/genam.h"
19 #include "access/gist.h"
20 #include "access/heapam.h"
21 #include "access/heapam_xlog.h"
22 #include "access/multixact.h"
23 #include "access/reloptions.h"
24 #include "access/relscan.h"
25 #include "access/sysattr.h"
26 #include "access/tableam.h"
28 #include "access/xact.h"
29 #include "access/xlog.h"
30 #include "access/xloginsert.h"
31 #include "catalog/catalog.h"
32 #include "catalog/heap.h"
33 #include "catalog/index.h"
34 #include "catalog/namespace.h"
35 #include "catalog/objectaccess.h"
36 #include "catalog/partition.h"
37 #include "catalog/pg_am.h"
38 #include "catalog/pg_attrdef.h"
39 #include "catalog/pg_collation.h"
40 #include "catalog/pg_constraint.h"
41 #include "catalog/pg_depend.h"
43 #include "catalog/pg_inherits.h"
44 #include "catalog/pg_largeobject.h"
45 #include "catalog/pg_namespace.h"
46 #include "catalog/pg_opclass.h"
47 #include "catalog/pg_policy.h"
48 #include "catalog/pg_rewrite.h"
50 #include "catalog/pg_tablespace.h"
51 #include "catalog/pg_trigger.h"
52 #include "catalog/pg_type.h"
53 #include "catalog/storage.h"
54 #include "catalog/storage_xlog.h"
55 #include "catalog/toasting.h"
56 #include "commands/cluster.h"
57 #include "commands/comment.h"
58 #include "commands/defrem.h"
59 #include "commands/event_trigger.h"
60 #include "commands/sequence.h"
61 #include "commands/tablecmds.h"
62 #include "commands/tablespace.h"
63 #include "commands/trigger.h"
64 #include "commands/typecmds.h"
65 #include "commands/user.h"
66 #include "commands/vacuum.h"
67 #include "executor/executor.h"
68 #include "foreign/fdwapi.h"
69 #include "foreign/foreign.h"
70 #include "miscadmin.h"
71 #include "nodes/makefuncs.h"
72 #include "nodes/nodeFuncs.h"
73 #include "nodes/parsenodes.h"
74 #include "optimizer/optimizer.h"
75 #include "parser/parse_coerce.h"
76 #include "parser/parse_collate.h"
77 #include "parser/parse_expr.h"
78 #include "parser/parse_relation.h"
79 #include "parser/parse_type.h"
80 #include "parser/parse_utilcmd.h"
81 #include "parser/parser.h"
83 #include "partitioning/partdesc.h"
84 #include "pgstat.h"
85 #include "rewrite/rewriteDefine.h"
86 #include "rewrite/rewriteHandler.h"
87 #include "rewrite/rewriteManip.h"
88 #include "storage/bufmgr.h"
89 #include "storage/lmgr.h"
90 #include "storage/lock.h"
91 #include "storage/predicate.h"
92 #include "storage/smgr.h"
93 #include "tcop/utility.h"
94 #include "utils/acl.h"
95 #include "utils/builtins.h"
96 #include "utils/fmgroids.h"
97 #include "utils/inval.h"
98 #include "utils/lsyscache.h"
99 #include "utils/memutils.h"
100 #include "utils/partcache.h"
101 #include "utils/relcache.h"
102 #include "utils/ruleutils.h"
103 #include "utils/snapmgr.h"
104 #include "utils/syscache.h"
105 #include "utils/timestamp.h"
106 #include "utils/typcache.h"
107 #include "utils/usercontext.h"
108 
109 /*
110  * ON COMMIT action list
111  */
112 typedef struct OnCommitItem
113 {
114  Oid relid; /* relid of relation */
115  OnCommitAction oncommit; /* what to do at end of xact */
116 
117  /*
118  * If this entry was created during the current transaction,
119  * creating_subid is the ID of the creating subxact; if created in a prior
120  * transaction, creating_subid is zero. If deleted during the current
121  * transaction, deleting_subid is the ID of the deleting subxact; if no
122  * deletion request is pending, deleting_subid is zero.
123  */
127 
128 static List *on_commits = NIL;
129 
130 
131 /*
132  * State information for ALTER TABLE
133  *
134  * The pending-work queue for an ALTER TABLE is a List of AlteredTableInfo
135  * structs, one for each table modified by the operation (the named table
136  * plus any child tables that are affected). We save lists of subcommands
137  * to apply to this table (possibly modified by parse transformation steps);
138  * these lists will be executed in Phase 2. If a Phase 3 step is needed,
139  * necessary information is stored in the constraints and newvals lists.
140  *
141  * Phase 2 is divided into multiple passes; subcommands are executed in
142  * a pass determined by subcommand type.
143  */
144 
145 typedef enum AlterTablePass
146 {
147  AT_PASS_UNSET = -1, /* UNSET will cause ERROR */
148  AT_PASS_DROP, /* DROP (all flavors) */
149  AT_PASS_ALTER_TYPE, /* ALTER COLUMN TYPE */
150  AT_PASS_ADD_COL, /* ADD COLUMN */
151  AT_PASS_SET_EXPRESSION, /* ALTER SET EXPRESSION */
152  AT_PASS_OLD_COL_ATTRS, /* re-install attnotnull */
153  AT_PASS_OLD_INDEX, /* re-add existing indexes */
154  AT_PASS_OLD_CONSTR, /* re-add existing constraints */
155  /* We could support a RENAME COLUMN pass here, but not currently used */
156  AT_PASS_ADD_CONSTR, /* ADD constraints (initial examination) */
157  AT_PASS_COL_ATTRS, /* set column attributes, eg NOT NULL */
158  AT_PASS_ADD_INDEXCONSTR, /* ADD index-based constraints */
159  AT_PASS_ADD_INDEX, /* ADD indexes */
160  AT_PASS_ADD_OTHERCONSTR, /* ADD other constraints, defaults */
161  AT_PASS_MISC, /* other stuff */
163 
164 #define AT_NUM_PASSES (AT_PASS_MISC + 1)
165 
166 typedef struct AlteredTableInfo
167 {
168  /* Information saved before any work commences: */
169  Oid relid; /* Relation to work on */
170  char relkind; /* Its relkind */
171  TupleDesc oldDesc; /* Pre-modification tuple descriptor */
172 
173  /*
174  * Transiently set during Phase 2, normally set to NULL.
175  *
176  * ATRewriteCatalogs sets this when it starts, and closes when ATExecCmd
177  * returns control. This can be exploited by ATExecCmd subroutines to
178  * close/reopen across transaction boundaries.
179  */
181 
182  /* Information saved by Phase 1 for Phase 2: */
183  List *subcmds[AT_NUM_PASSES]; /* Lists of AlterTableCmd */
184  /* Information saved by Phases 1/2 for Phase 3: */
185  List *constraints; /* List of NewConstraint */
186  List *newvals; /* List of NewColumnValue */
187  List *afterStmts; /* List of utility command parsetrees */
188  bool verify_new_notnull; /* T if we should recheck NOT NULL */
189  int rewrite; /* Reason for forced rewrite, if any */
190  bool chgAccessMethod; /* T if SET ACCESS METHOD is used */
191  Oid newAccessMethod; /* new access method; 0 means no change,
192  * if above is true */
193  Oid newTableSpace; /* new tablespace; 0 means no change */
194  bool chgPersistence; /* T if SET LOGGED/UNLOGGED is used */
195  char newrelpersistence; /* if above is true */
196  Expr *partition_constraint; /* for attach partition validation */
197  /* true, if validating default due to some other attach/detach */
199  /* Objects to rebuild after completing ALTER TYPE operations */
200  List *changedConstraintOids; /* OIDs of constraints to rebuild */
201  List *changedConstraintDefs; /* string definitions of same */
202  List *changedIndexOids; /* OIDs of indexes to rebuild */
203  List *changedIndexDefs; /* string definitions of same */
204  char *replicaIdentityIndex; /* index to reset as REPLICA IDENTITY */
205  char *clusterOnIndex; /* index to use for CLUSTER */
206  List *changedStatisticsOids; /* OIDs of statistics to rebuild */
207  List *changedStatisticsDefs; /* string definitions of same */
209 
210 /* Struct describing one new constraint to check in Phase 3 scan */
211 /* Note: new not-null constraints are handled elsewhere */
212 typedef struct NewConstraint
213 {
214  char *name; /* Constraint name, or NULL if none */
215  ConstrType contype; /* CHECK or FOREIGN */
216  Oid refrelid; /* PK rel, if FOREIGN */
217  Oid refindid; /* OID of PK's index, if FOREIGN */
218  bool conwithperiod; /* Whether the new FOREIGN KEY uses PERIOD */
219  Oid conid; /* OID of pg_constraint entry, if FOREIGN */
220  Node *qual; /* Check expr or CONSTR_FOREIGN Constraint */
221  ExprState *qualstate; /* Execution state for CHECK expr */
223 
224 /*
225  * Struct describing one new column value that needs to be computed during
226  * Phase 3 copy (this could be either a new column with a non-null default, or
227  * a column that we're changing the type of). Columns without such an entry
228  * are just copied from the old table during ATRewriteTable. Note that the
229  * expr is an expression over *old* table values, except when is_generated
230  * is true; then it is an expression over columns of the *new* tuple.
231  */
232 typedef struct NewColumnValue
233 {
234  AttrNumber attnum; /* which column */
235  Expr *expr; /* expression to compute */
236  ExprState *exprstate; /* execution state */
237  bool is_generated; /* is it a GENERATED expression? */
239 
240 /*
241  * Error-reporting support for RemoveRelations
242  */
244 {
245  char kind;
247  const char *nonexistent_msg;
248  const char *skipping_msg;
249  const char *nota_msg;
250  const char *drophint_msg;
251 };
252 
253 static const struct dropmsgstrings dropmsgstringarray[] = {
254  {RELKIND_RELATION,
256  gettext_noop("table \"%s\" does not exist"),
257  gettext_noop("table \"%s\" does not exist, skipping"),
258  gettext_noop("\"%s\" is not a table"),
259  gettext_noop("Use DROP TABLE to remove a table.")},
260  {RELKIND_SEQUENCE,
262  gettext_noop("sequence \"%s\" does not exist"),
263  gettext_noop("sequence \"%s\" does not exist, skipping"),
264  gettext_noop("\"%s\" is not a sequence"),
265  gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
266  {RELKIND_VIEW,
268  gettext_noop("view \"%s\" does not exist"),
269  gettext_noop("view \"%s\" does not exist, skipping"),
270  gettext_noop("\"%s\" is not a view"),
271  gettext_noop("Use DROP VIEW to remove a view.")},
272  {RELKIND_MATVIEW,
274  gettext_noop("materialized view \"%s\" does not exist"),
275  gettext_noop("materialized view \"%s\" does not exist, skipping"),
276  gettext_noop("\"%s\" is not a materialized view"),
277  gettext_noop("Use DROP MATERIALIZED VIEW to remove a materialized view.")},
278  {RELKIND_INDEX,
279  ERRCODE_UNDEFINED_OBJECT,
280  gettext_noop("index \"%s\" does not exist"),
281  gettext_noop("index \"%s\" does not exist, skipping"),
282  gettext_noop("\"%s\" is not an index"),
283  gettext_noop("Use DROP INDEX to remove an index.")},
284  {RELKIND_COMPOSITE_TYPE,
285  ERRCODE_UNDEFINED_OBJECT,
286  gettext_noop("type \"%s\" does not exist"),
287  gettext_noop("type \"%s\" does not exist, skipping"),
288  gettext_noop("\"%s\" is not a type"),
289  gettext_noop("Use DROP TYPE to remove a type.")},
290  {RELKIND_FOREIGN_TABLE,
291  ERRCODE_UNDEFINED_OBJECT,
292  gettext_noop("foreign table \"%s\" does not exist"),
293  gettext_noop("foreign table \"%s\" does not exist, skipping"),
294  gettext_noop("\"%s\" is not a foreign table"),
295  gettext_noop("Use DROP FOREIGN TABLE to remove a foreign table.")},
296  {RELKIND_PARTITIONED_TABLE,
298  gettext_noop("table \"%s\" does not exist"),
299  gettext_noop("table \"%s\" does not exist, skipping"),
300  gettext_noop("\"%s\" is not a table"),
301  gettext_noop("Use DROP TABLE to remove a table.")},
302  {RELKIND_PARTITIONED_INDEX,
303  ERRCODE_UNDEFINED_OBJECT,
304  gettext_noop("index \"%s\" does not exist"),
305  gettext_noop("index \"%s\" does not exist, skipping"),
306  gettext_noop("\"%s\" is not an index"),
307  gettext_noop("Use DROP INDEX to remove an index.")},
308  {'\0', 0, NULL, NULL, NULL, NULL}
309 };
310 
311 /* communication between RemoveRelations and RangeVarCallbackForDropRelation */
313 {
314  /* These fields are set by RemoveRelations: */
317  /* These fields are state to track which subsidiary locks are held: */
320  /* These fields are passed back by RangeVarCallbackForDropRelation: */
323 };
324 
325 /* Alter table target-type flags for ATSimplePermissions */
326 #define ATT_TABLE 0x0001
327 #define ATT_VIEW 0x0002
328 #define ATT_MATVIEW 0x0004
329 #define ATT_INDEX 0x0008
330 #define ATT_COMPOSITE_TYPE 0x0010
331 #define ATT_FOREIGN_TABLE 0x0020
332 #define ATT_PARTITIONED_INDEX 0x0040
333 #define ATT_SEQUENCE 0x0080
334 
335 /*
336  * ForeignTruncateInfo
337  *
338  * Information related to truncation of foreign tables. This is used for
339  * the elements in a hash table. It uses the server OID as lookup key,
340  * and includes a per-server list of all foreign tables involved in the
341  * truncation.
342  */
343 typedef struct ForeignTruncateInfo
344 {
348 
349 /*
350  * Partition tables are expected to be dropped when the parent partitioned
351  * table gets dropped. Hence for partitioning we use AUTO dependency.
352  * Otherwise, for regular inheritance use NORMAL dependency.
353  */
354 #define child_dependency_type(child_is_partition) \
355  ((child_is_partition) ? DEPENDENCY_AUTO : DEPENDENCY_NORMAL)
356 
357 static void truncate_check_rel(Oid relid, Form_pg_class reltuple);
358 static void truncate_check_perms(Oid relid, Form_pg_class reltuple);
359 static void truncate_check_activity(Relation rel);
360 static void RangeVarCallbackForTruncate(const RangeVar *relation,
361  Oid relId, Oid oldRelId, void *arg);
362 static List *MergeAttributes(List *columns, const List *supers, char relpersistence,
363  bool is_partition, List **supconstr,
364  List **supnotnulls);
365 static List *MergeCheckConstraint(List *constraints, const char *name, Node *expr);
366 static void MergeChildAttribute(List *inh_columns, int exist_attno, int newcol_attno, const ColumnDef *newdef);
367 static ColumnDef *MergeInheritedAttribute(List *inh_columns, int exist_attno, const ColumnDef *newdef);
368 static void MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel, bool ispartition);
369 static void MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel);
370 static void StoreCatalogInheritance(Oid relationId, List *supers,
371  bool child_is_partition);
372 static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
373  int32 seqNumber, Relation inhRelation,
374  bool child_is_partition);
375 static int findAttrByName(const char *attributeName, const List *columns);
376 static void AlterIndexNamespaces(Relation classRel, Relation rel,
377  Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved);
378 static void AlterSeqNamespaces(Relation classRel, Relation rel,
379  Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved,
380  LOCKMODE lockmode);
382  bool recurse, bool recursing, LOCKMODE lockmode);
383 static bool ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
384  Relation rel, HeapTuple contuple, List **otherrelids,
385  LOCKMODE lockmode);
387  Relation rel, char *constrName,
388  bool recurse, bool recursing, LOCKMODE lockmode);
389 static int transformColumnNameList(Oid relId, List *colList,
390  int16 *attnums, Oid *atttypids);
391 static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
392  List **attnamelist,
393  int16 *attnums, Oid *atttypids,
394  Oid *opclasses, bool *pk_has_without_overlaps);
396  int numattrs, int16 *attnums,
397  bool with_period, Oid *opclasses,
398  bool *pk_has_without_overlaps);
399 static void checkFkeyPermissions(Relation rel, int16 *attnums, int natts);
400 static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
401  Oid *funcid);
402 static void validateForeignKeyConstraint(char *conname,
403  Relation rel, Relation pkrel,
404  Oid pkindOid, Oid constraintOid, bool hasperiod);
405 static void ATController(AlterTableStmt *parsetree,
406  Relation rel, List *cmds, bool recurse, LOCKMODE lockmode,
408 static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
409  bool recurse, bool recursing, LOCKMODE lockmode,
411 static void ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode,
413 static void ATExecCmd(List **wqueue, AlteredTableInfo *tab,
414  AlterTableCmd *cmd, LOCKMODE lockmode, AlterTablePass cur_pass,
417  Relation rel, AlterTableCmd *cmd,
418  bool recurse, LOCKMODE lockmode,
419  AlterTablePass cur_pass,
421 static void ATRewriteTables(AlterTableStmt *parsetree,
422  List **wqueue, LOCKMODE lockmode,
424 static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode);
425 static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);
426 static void ATSimplePermissions(AlterTableType cmdtype, Relation rel, int allowed_targets);
427 static void ATSimpleRecursion(List **wqueue, Relation rel,
428  AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode,
430 static void ATCheckPartitionsNotInUse(Relation rel, LOCKMODE lockmode);
431 static void ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
432  LOCKMODE lockmode,
434 static List *find_typed_table_dependencies(Oid typeOid, const char *typeName,
435  DropBehavior behavior);
436 static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
437  bool is_view, AlterTableCmd *cmd, LOCKMODE lockmode,
439 static ObjectAddress ATExecAddColumn(List **wqueue, AlteredTableInfo *tab,
440  Relation rel, AlterTableCmd **cmd,
441  bool recurse, bool recursing,
442  LOCKMODE lockmode, AlterTablePass cur_pass,
444 static bool check_for_column_name_collision(Relation rel, const char *colname,
445  bool if_not_exists);
446 static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid);
448 static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, bool recurse,
449  LOCKMODE lockmode);
450 static bool set_attnotnull(List **wqueue, Relation rel,
451  AttrNumber attnum, bool recurse, LOCKMODE lockmode);
452 static ObjectAddress ATExecSetNotNull(List **wqueue, Relation rel,
453  char *constrname, char *colName,
454  bool recurse, bool recursing,
455  List **readyRels, LOCKMODE lockmode);
456 static ObjectAddress ATExecSetAttNotNull(List **wqueue, Relation rel,
457  const char *colName, LOCKMODE lockmode);
459 static bool ConstraintImpliedByRelConstraint(Relation scanrel,
460  List *testConstraint, List *provenConstraint);
461 static ObjectAddress ATExecColumnDefault(Relation rel, const char *colName,
462  Node *newDefault, LOCKMODE lockmode);
464  Node *newDefault);
465 static ObjectAddress ATExecAddIdentity(Relation rel, const char *colName,
466  Node *def, LOCKMODE lockmode, bool recurse, bool recursing);
467 static ObjectAddress ATExecSetIdentity(Relation rel, const char *colName,
468  Node *def, LOCKMODE lockmode, bool recurse, bool recursing);
469 static ObjectAddress ATExecDropIdentity(Relation rel, const char *colName, bool missing_ok, LOCKMODE lockmode,
470  bool recurse, bool recursing);
471 static ObjectAddress ATExecSetExpression(AlteredTableInfo *tab, Relation rel, const char *colName,
472  Node *newExpr, LOCKMODE lockmode);
473 static void ATPrepDropExpression(Relation rel, AlterTableCmd *cmd, bool recurse, bool recursing, LOCKMODE lockmode);
474 static ObjectAddress ATExecDropExpression(Relation rel, const char *colName, bool missing_ok, LOCKMODE lockmode);
475 static ObjectAddress ATExecSetStatistics(Relation rel, const char *colName, int16 colNum,
476  Node *newValue, LOCKMODE lockmode);
477 static ObjectAddress ATExecSetOptions(Relation rel, const char *colName,
478  Node *options, bool isReset, LOCKMODE lockmode);
479 static ObjectAddress ATExecSetStorage(Relation rel, const char *colName,
480  Node *newValue, LOCKMODE lockmode);
481 static void ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
482  AlterTableCmd *cmd, LOCKMODE lockmode,
484 static ObjectAddress ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
485  DropBehavior behavior,
486  bool recurse, bool recursing,
487  bool missing_ok, LOCKMODE lockmode,
488  ObjectAddresses *addrs);
489 static void ATPrepAddPrimaryKey(List **wqueue, Relation rel, AlterTableCmd *cmd,
492  IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode);
494  CreateStatsStmt *stmt, bool is_rebuild, LOCKMODE lockmode);
495 static ObjectAddress ATExecAddConstraint(List **wqueue,
496  AlteredTableInfo *tab, Relation rel,
497  Constraint *newConstraint, bool recurse, bool is_readd,
498  LOCKMODE lockmode);
499 static char *ChooseForeignKeyConstraintNameAddition(List *colnames);
501  IndexStmt *stmt, LOCKMODE lockmode);
503  AlteredTableInfo *tab, Relation rel,
504  Constraint *constr,
505  bool recurse, bool recursing, bool is_readd,
506  LOCKMODE lockmode);
508  Relation rel, Constraint *fkconstraint,
509  bool recurse, bool recursing,
510  LOCKMODE lockmode);
511 static ObjectAddress addFkRecurseReferenced(List **wqueue, Constraint *fkconstraint,
512  Relation rel, Relation pkrel, Oid indexOid, Oid parentConstr,
513  int numfks, int16 *pkattnum, int16 *fkattnum,
514  Oid *pfeqoperators, Oid *ppeqoperators, Oid *ffeqoperators,
515  int numfkdelsetcols, int16 *fkdelsetcols,
516  bool old_check_ok,
517  Oid parentDelTrigger, Oid parentUpdTrigger,
518  bool with_period);
519 static void validateFkOnDeleteSetColumns(int numfks, const int16 *fkattnums,
520  int numfksetcols, const int16 *fksetcolsattnums,
521  List *fksetcols);
522 static void addFkRecurseReferencing(List **wqueue, Constraint *fkconstraint,
523  Relation rel, Relation pkrel, Oid indexOid, Oid parentConstr,
524  int numfks, int16 *pkattnum, int16 *fkattnum,
525  Oid *pfeqoperators, Oid *ppeqoperators, Oid *ffeqoperators,
526  int numfkdelsetcols, int16 *fkdelsetcols,
527  bool old_check_ok, LOCKMODE lockmode,
528  Oid parentInsTrigger, Oid parentUpdTrigger,
529  bool with_period);
530 
531 static void CloneForeignKeyConstraints(List **wqueue, Relation parentRel,
532  Relation partitionRel);
533 static void CloneFkReferenced(Relation parentRel, Relation partitionRel);
534 static void CloneFkReferencing(List **wqueue, Relation parentRel,
535  Relation partRel);
536 static void createForeignKeyCheckTriggers(Oid myRelOid, Oid refRelOid,
537  Constraint *fkconstraint, Oid constraintOid,
538  Oid indexOid,
539  Oid parentInsTrigger, Oid parentUpdTrigger,
540  Oid *insertTrigOid, Oid *updateTrigOid);
541 static void createForeignKeyActionTriggers(Relation rel, Oid refRelOid,
542  Constraint *fkconstraint, Oid constraintOid,
543  Oid indexOid,
544  Oid parentDelTrigger, Oid parentUpdTrigger,
545  Oid *deleteTrigOid, Oid *updateTrigOid);
547  Oid partRelid,
548  Oid parentConstrOid, int numfks,
549  AttrNumber *mapped_conkey, AttrNumber *confkey,
550  Oid *conpfeqop,
551  Oid parentInsTrigger,
552  Oid parentUpdTrigger,
553  Relation trigrel);
554 static void GetForeignKeyActionTriggers(Relation trigrel,
555  Oid conoid, Oid confrelid, Oid conrelid,
556  Oid *deleteTriggerOid,
557  Oid *updateTriggerOid);
558 static void GetForeignKeyCheckTriggers(Relation trigrel,
559  Oid conoid, Oid confrelid, Oid conrelid,
560  Oid *insertTriggerOid,
561  Oid *updateTriggerOid);
562 static void ATExecDropConstraint(Relation rel, const char *constrName,
563  DropBehavior behavior, bool recurse,
564  bool missing_ok, LOCKMODE lockmode);
566  HeapTuple constraintTup, DropBehavior behavior,
567  bool recurse, bool recursing,
568  bool missing_ok, List **readyRels,
569  LOCKMODE lockmode);
570 static void ATPrepAlterColumnType(List **wqueue,
571  AlteredTableInfo *tab, Relation rel,
572  bool recurse, bool recursing,
573  AlterTableCmd *cmd, LOCKMODE lockmode,
575 static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno);
577  AlterTableCmd *cmd, LOCKMODE lockmode);
579  Relation rel, AttrNumber attnum, const char *colName);
580 static void RememberConstraintForRebuilding(Oid conoid, AlteredTableInfo *tab);
581 static void RememberIndexForRebuilding(Oid indoid, AlteredTableInfo *tab);
582 static void RememberStatisticsForRebuilding(Oid stxoid, AlteredTableInfo *tab);
583 static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab,
584  LOCKMODE lockmode);
585 static void ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId,
586  char *cmd, List **wqueue, LOCKMODE lockmode,
587  bool rewrite);
589  Oid objid, Relation rel, List *domname,
590  const char *conname);
591 static void TryReuseIndex(Oid oldId, IndexStmt *stmt);
592 static void TryReuseForeignKey(Oid oldId, Constraint *con);
593 static ObjectAddress ATExecAlterColumnGenericOptions(Relation rel, const char *colName,
594  List *options, LOCKMODE lockmode);
595 static void change_owner_fix_column_acls(Oid relationOid,
596  Oid oldOwnerId, Oid newOwnerId);
597 static void change_owner_recurse_to_sequences(Oid relationOid,
598  Oid newOwnerId, LOCKMODE lockmode);
599 static ObjectAddress ATExecClusterOn(Relation rel, const char *indexName,
600  LOCKMODE lockmode);
601 static void ATExecDropCluster(Relation rel, LOCKMODE lockmode);
602 static void ATPrepSetAccessMethod(AlteredTableInfo *tab, Relation rel, const char *amname);
603 static void ATExecSetAccessMethodNoStorage(Relation rel, Oid newAccessMethod);
604 static bool ATPrepChangePersistence(Relation rel, bool toLogged);
605 static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
606  const char *tablespacename, LOCKMODE lockmode);
607 static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode);
608 static void ATExecSetTableSpaceNoStorage(Relation rel, Oid newTableSpace);
609 static void ATExecSetRelOptions(Relation rel, List *defList,
610  AlterTableType operation,
611  LOCKMODE lockmode);
612 static void ATExecEnableDisableTrigger(Relation rel, const char *trigname,
613  char fires_when, bool skip_system, bool recurse,
614  LOCKMODE lockmode);
615 static void ATExecEnableDisableRule(Relation rel, const char *rulename,
616  char fires_when, LOCKMODE lockmode);
617 static void ATPrepAddInherit(Relation child_rel);
618 static ObjectAddress ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode);
619 static ObjectAddress ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode);
620 static void drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid,
621  DependencyType deptype);
622 static ObjectAddress ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode);
623 static void ATExecDropOf(Relation rel, LOCKMODE lockmode);
624 static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode);
625 static void ATExecGenericOptions(Relation rel, List *options);
626 static void ATExecSetRowSecurity(Relation rel, bool rls);
627 static void ATExecForceNoForceRowSecurity(Relation rel, bool force_rls);
629  const char *column, Node *newValue, LOCKMODE lockmode);
630 
631 static void index_copy_data(Relation rel, RelFileLocator newrlocator);
632 static const char *storage_name(char c);
633 
634 static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid,
635  Oid oldRelOid, void *arg);
636 static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
637  Oid oldrelid, void *arg);
639 static void ComputePartitionAttrs(ParseState *pstate, Relation rel, List *partParams, AttrNumber *partattrs,
640  List **partexprs, Oid *partopclass, Oid *partcollation,
641  PartitionStrategy strategy);
642 static void CreateInheritance(Relation child_rel, Relation parent_rel, bool ispartition);
643 static void RemoveInheritance(Relation child_rel, Relation parent_rel,
644  bool expect_detached);
645 static void ATInheritAdjustNotNulls(Relation parent_rel, Relation child_rel,
646  int inhcount);
647 static ObjectAddress ATExecAttachPartition(List **wqueue, Relation rel,
648  PartitionCmd *cmd,
650 static void AttachPartitionEnsureIndexes(List **wqueue, Relation rel, Relation attachrel);
651 static void QueuePartitionConstraintValidation(List **wqueue, Relation scanrel,
652  List *partConstraint,
653  bool validate_default);
654 static void CloneRowTriggersToPartition(Relation parent, Relation partition);
655 static void DetachAddConstraintIfNeeded(List **wqueue, Relation partRel);
656 static void DropClonedTriggersFromPartition(Oid partitionId);
658  Relation rel, RangeVar *name,
659  bool concurrent);
660 static void DetachPartitionFinalize(Relation rel, Relation partRel,
661  bool concurrent, Oid defaultPartOid);
663 static ObjectAddress ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx,
664  RangeVar *name);
665 static void validatePartitionedIndex(Relation partedIdx, Relation partedTbl);
666 static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx,
667  Relation partitionTbl);
668 static void verifyPartitionIndexNotNull(IndexInfo *iinfo, Relation partIdx);
669 static List *GetParentedForeignKeyRefs(Relation partition);
670 static void ATDetachCheckNoForeignKeyRefs(Relation partition);
671 static char GetAttributeCompression(Oid atttypid, const char *compression);
672 static char GetAttributeStorage(Oid atttypid, const char *storagemode);
673 
674 static void ATExecSplitPartition(List **wqueue, AlteredTableInfo *tab,
675  Relation rel, PartitionCmd *cmd,
677 static void ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel,
679 
680 /* ----------------------------------------------------------------
681  * DefineRelation
682  * Creates a new relation.
683  *
684  * stmt carries parsetree information from an ordinary CREATE TABLE statement.
685  * The other arguments are used to extend the behavior for other cases:
686  * relkind: relkind to assign to the new relation
687  * ownerId: if not InvalidOid, use this as the new relation's owner.
688  * typaddress: if not null, it's set to the pg_type entry's address.
689  * queryString: for error reporting
690  *
691  * Note that permissions checks are done against current user regardless of
692  * ownerId. A nonzero ownerId is used when someone is creating a relation
693  * "on behalf of" someone else, so we still want to see that the current user
694  * has permissions to do it.
695  *
696  * If successful, returns the address of the new relation.
697  * ----------------------------------------------------------------
698  */
700 DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
701  ObjectAddress *typaddress, const char *queryString)
702 {
703  char relname[NAMEDATALEN];
704  Oid namespaceId;
705  Oid relationId;
706  Oid tablespaceId;
707  Relation rel;
709  List *inheritOids;
710  List *old_constraints;
711  List *old_notnulls;
712  List *rawDefaults;
713  List *cookedDefaults;
714  List *nncols;
715  Datum reloptions;
716  ListCell *listptr;
718  bool partitioned;
719  static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
720  Oid ofTypeId;
721  ObjectAddress address;
722  LOCKMODE parentLockmode;
723  Oid accessMethodId = InvalidOid;
724 
725  /*
726  * Truncate relname to appropriate length (probably a waste of time, as
727  * parser should have done this already).
728  */
729  strlcpy(relname, stmt->relation->relname, NAMEDATALEN);
730 
731  /*
732  * Check consistency of arguments
733  */
734  if (stmt->oncommit != ONCOMMIT_NOOP
735  && stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
736  ereport(ERROR,
737  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
738  errmsg("ON COMMIT can only be used on temporary tables")));
739 
740  if (stmt->partspec != NULL)
741  {
742  if (relkind != RELKIND_RELATION)
743  elog(ERROR, "unexpected relkind: %d", (int) relkind);
744 
745  relkind = RELKIND_PARTITIONED_TABLE;
746  partitioned = true;
747  }
748  else
749  partitioned = false;
750 
751  /*
752  * Look up the namespace in which we are supposed to create the relation,
753  * check we have permission to create there, lock it against concurrent
754  * drop, and mark stmt->relation as RELPERSISTENCE_TEMP if a temporary
755  * namespace is selected.
756  */
757  namespaceId =
759 
760  /*
761  * Security check: disallow creating temp tables from security-restricted
762  * code. This is needed because calling code might not expect untrusted
763  * tables to appear in pg_temp at the front of its search path.
764  */
765  if (stmt->relation->relpersistence == RELPERSISTENCE_TEMP
767  ereport(ERROR,
768  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
769  errmsg("cannot create temporary table within security-restricted operation")));
770 
771  /*
772  * Determine the lockmode to use when scanning parents. A self-exclusive
773  * lock is needed here.
774  *
775  * For regular inheritance, if two backends attempt to add children to the
776  * same parent simultaneously, and that parent has no pre-existing
777  * children, then both will attempt to update the parent's relhassubclass
778  * field, leading to a "tuple concurrently updated" error. Also, this
779  * interlocks against a concurrent ANALYZE on the parent table, which
780  * might otherwise be attempting to clear the parent's relhassubclass
781  * field, if its previous children were recently dropped.
782  *
783  * If the child table is a partition, then we instead grab an exclusive
784  * lock on the parent because its partition descriptor will be changed by
785  * addition of the new partition.
786  */
787  parentLockmode = (stmt->partbound != NULL ? AccessExclusiveLock :
789 
790  /* Determine the list of OIDs of the parents. */
791  inheritOids = NIL;
792  foreach(listptr, stmt->inhRelations)
793  {
794  RangeVar *rv = (RangeVar *) lfirst(listptr);
795  Oid parentOid;
796 
797  parentOid = RangeVarGetRelid(rv, parentLockmode, false);
798 
799  /*
800  * Reject duplications in the list of parents.
801  */
802  if (list_member_oid(inheritOids, parentOid))
803  ereport(ERROR,
804  (errcode(ERRCODE_DUPLICATE_TABLE),
805  errmsg("relation \"%s\" would be inherited from more than once",
806  get_rel_name(parentOid))));
807 
808  inheritOids = lappend_oid(inheritOids, parentOid);
809  }
810 
811  /*
812  * Select tablespace to use: an explicitly indicated one, or (in the case
813  * of a partitioned table) the parent's, if it has one.
814  */
815  if (stmt->tablespacename)
816  {
817  tablespaceId = get_tablespace_oid(stmt->tablespacename, false);
818 
819  if (partitioned && tablespaceId == MyDatabaseTableSpace)
820  ereport(ERROR,
821  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
822  errmsg("cannot specify default tablespace for partitioned relations")));
823  }
824  else if (stmt->partbound)
825  {
826  Assert(list_length(inheritOids) == 1);
827  tablespaceId = get_rel_tablespace(linitial_oid(inheritOids));
828  }
829  else
830  tablespaceId = InvalidOid;
831 
832  /* still nothing? use the default */
833  if (!OidIsValid(tablespaceId))
834  tablespaceId = GetDefaultTablespace(stmt->relation->relpersistence,
835  partitioned);
836 
837  /* Check permissions except when using database's default */
838  if (OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
839  {
840  AclResult aclresult;
841 
842  aclresult = object_aclcheck(TableSpaceRelationId, tablespaceId, GetUserId(),
843  ACL_CREATE);
844  if (aclresult != ACLCHECK_OK)
846  get_tablespace_name(tablespaceId));
847  }
848 
849  /* In all cases disallow placing user relations in pg_global */
850  if (tablespaceId == GLOBALTABLESPACE_OID)
851  ereport(ERROR,
852  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
853  errmsg("only shared relations can be placed in pg_global tablespace")));
854 
855  /* Identify user ID that will own the table */
856  if (!OidIsValid(ownerId))
857  ownerId = GetUserId();
858 
859  /*
860  * Parse and validate reloptions, if any.
861  */
862  reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
863  true, false);
864 
865  switch (relkind)
866  {
867  case RELKIND_VIEW:
868  (void) view_reloptions(reloptions, true);
869  break;
870  case RELKIND_PARTITIONED_TABLE:
871  (void) partitioned_table_reloptions(reloptions, true);
872  break;
873  default:
874  (void) heap_reloptions(relkind, reloptions, true);
875  }
876 
877  if (stmt->ofTypename)
878  {
879  AclResult aclresult;
880 
881  ofTypeId = typenameTypeId(NULL, stmt->ofTypename);
882 
883  aclresult = object_aclcheck(TypeRelationId, ofTypeId, GetUserId(), ACL_USAGE);
884  if (aclresult != ACLCHECK_OK)
885  aclcheck_error_type(aclresult, ofTypeId);
886  }
887  else
888  ofTypeId = InvalidOid;
889 
890  /*
891  * Look up inheritance ancestors and generate relation schema, including
892  * inherited attributes. (Note that stmt->tableElts is destructively
893  * modified by MergeAttributes.)
894  */
895  stmt->tableElts =
896  MergeAttributes(stmt->tableElts, inheritOids,
897  stmt->relation->relpersistence,
898  stmt->partbound != NULL,
899  &old_constraints, &old_notnulls);
900 
901  /*
902  * Create a tuple descriptor from the relation schema. Note that this
903  * deals with column names, types, and in-descriptor NOT NULL flags, but
904  * not default values, NOT NULL or CHECK constraints; we handle those
905  * below.
906  */
907  descriptor = BuildDescForRelation(stmt->tableElts);
908 
909  /*
910  * Find columns with default values and prepare for insertion of the
911  * defaults. Pre-cooked (that is, inherited) defaults go into a list of
912  * CookedConstraint structs that we'll pass to heap_create_with_catalog,
913  * while raw defaults go into a list of RawColumnDefault structs that will
914  * be processed by AddRelationNewConstraints. (We can't deal with raw
915  * expressions until we can do transformExpr.)
916  *
917  * We can set the atthasdef flags now in the tuple descriptor; this just
918  * saves StoreAttrDefault from having to do an immediate update of the
919  * pg_attribute rows.
920  */
921  rawDefaults = NIL;
922  cookedDefaults = NIL;
923  attnum = 0;
924 
925  foreach(listptr, stmt->tableElts)
926  {
927  ColumnDef *colDef = lfirst(listptr);
928  Form_pg_attribute attr;
929 
930  attnum++;
931  attr = TupleDescAttr(descriptor, attnum - 1);
932 
933  if (colDef->raw_default != NULL)
934  {
935  RawColumnDefault *rawEnt;
936 
937  Assert(colDef->cooked_default == NULL);
938 
939  rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
940  rawEnt->attnum = attnum;
941  rawEnt->raw_default = colDef->raw_default;
942  rawEnt->missingMode = false;
943  rawEnt->generated = colDef->generated;
944  rawDefaults = lappend(rawDefaults, rawEnt);
945  attr->atthasdef = true;
946  }
947  else if (colDef->cooked_default != NULL)
948  {
949  CookedConstraint *cooked;
950 
951  cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
952  cooked->contype = CONSTR_DEFAULT;
953  cooked->conoid = InvalidOid; /* until created */
954  cooked->name = NULL;
955  cooked->attnum = attnum;
956  cooked->expr = colDef->cooked_default;
957  cooked->skip_validation = false;
958  cooked->is_local = true; /* not used for defaults */
959  cooked->inhcount = 0; /* ditto */
960  cooked->is_no_inherit = false;
961  cookedDefaults = lappend(cookedDefaults, cooked);
962  attr->atthasdef = true;
963  }
964  }
965 
966  /*
967  * For relations with table AM and partitioned tables, select access
968  * method to use: an explicitly indicated one, or (in the case of a
969  * partitioned table) the parent's, if it has one.
970  */
971  if (stmt->accessMethod != NULL)
972  {
973  Assert(RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_PARTITIONED_TABLE);
974  accessMethodId = get_table_am_oid(stmt->accessMethod, false);
975  }
976  else if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_PARTITIONED_TABLE)
977  {
978  if (stmt->partbound)
979  {
980  Assert(list_length(inheritOids) == 1);
981  accessMethodId = get_rel_relam(linitial_oid(inheritOids));
982  }
983 
984  if (RELKIND_HAS_TABLE_AM(relkind) && !OidIsValid(accessMethodId))
985  accessMethodId = get_table_am_oid(default_table_access_method, false);
986  }
987 
988  /*
989  * Create the relation. Inherited defaults and constraints are passed in
990  * for immediate handling --- since they don't need parsing, they can be
991  * stored immediately.
992  */
993  relationId = heap_create_with_catalog(relname,
994  namespaceId,
995  tablespaceId,
996  InvalidOid,
997  InvalidOid,
998  ofTypeId,
999  ownerId,
1000  accessMethodId,
1001  descriptor,
1002  list_concat(cookedDefaults,
1003  old_constraints),
1004  relkind,
1005  stmt->relation->relpersistence,
1006  false,
1007  false,
1008  stmt->oncommit,
1009  reloptions,
1010  true,
1012  false,
1013  InvalidOid,
1014  typaddress);
1015 
1016  /*
1017  * We must bump the command counter to make the newly-created relation
1018  * tuple visible for opening.
1019  */
1021 
1022  /*
1023  * Open the new relation and acquire exclusive lock on it. This isn't
1024  * really necessary for locking out other backends (since they can't see
1025  * the new rel anyway until we commit), but it keeps the lock manager from
1026  * complaining about deadlock risks.
1027  */
1028  rel = relation_open(relationId, AccessExclusiveLock);
1029 
1030  /*
1031  * Now add any newly specified column default and generation expressions
1032  * to the new relation. These are passed to us in the form of raw
1033  * parsetrees; we need to transform them to executable expression trees
1034  * before they can be added. The most convenient way to do that is to
1035  * apply the parser's transformExpr routine, but transformExpr doesn't
1036  * work unless we have a pre-existing relation. So, the transformation has
1037  * to be postponed to this final step of CREATE TABLE.
1038  *
1039  * This needs to be before processing the partitioning clauses because
1040  * those could refer to generated columns.
1041  */
1042  if (rawDefaults)
1043  AddRelationNewConstraints(rel, rawDefaults, NIL,
1044  true, true, false, queryString);
1045 
1046  /*
1047  * Make column generation expressions visible for use by partitioning.
1048  */
1050 
1051  /* Process and store partition bound, if any. */
1052  if (stmt->partbound)
1053  {
1054  PartitionBoundSpec *bound;
1055  ParseState *pstate;
1056  Oid parentId = linitial_oid(inheritOids),
1057  defaultPartOid;
1058  Relation parent,
1059  defaultRel = NULL;
1060  ParseNamespaceItem *nsitem;
1061 
1062  /* Already have strong enough lock on the parent */
1063  parent = table_open(parentId, NoLock);
1064 
1065  /*
1066  * We are going to try to validate the partition bound specification
1067  * against the partition key of parentRel, so it better have one.
1068  */
1069  if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1070  ereport(ERROR,
1071  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1072  errmsg("\"%s\" is not partitioned",
1073  RelationGetRelationName(parent))));
1074 
1075  /*
1076  * The partition constraint of the default partition depends on the
1077  * partition bounds of every other partition. It is possible that
1078  * another backend might be about to execute a query on the default
1079  * partition table, and that the query relies on previously cached
1080  * default partition constraints. We must therefore take a table lock
1081  * strong enough to prevent all queries on the default partition from
1082  * proceeding until we commit and send out a shared-cache-inval notice
1083  * that will make them update their index lists.
1084  *
1085  * Order of locking: The relation being added won't be visible to
1086  * other backends until it is committed, hence here in
1087  * DefineRelation() the order of locking the default partition and the
1088  * relation being added does not matter. But at all other places we
1089  * need to lock the default relation before we lock the relation being
1090  * added or removed i.e. we should take the lock in same order at all
1091  * the places such that lock parent, lock default partition and then
1092  * lock the partition so as to avoid a deadlock.
1093  */
1094  defaultPartOid =
1096  true));
1097  if (OidIsValid(defaultPartOid))
1098  defaultRel = table_open(defaultPartOid, AccessExclusiveLock);
1099 
1100  /* Transform the bound values */
1101  pstate = make_parsestate(NULL);
1102  pstate->p_sourcetext = queryString;
1103 
1104  /*
1105  * Add an nsitem containing this relation, so that transformExpr
1106  * called on partition bound expressions is able to report errors
1107  * using a proper context.
1108  */
1109  nsitem = addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
1110  NULL, false, false);
1111  addNSItemToQuery(pstate, nsitem, false, true, true);
1112 
1113  bound = transformPartitionBound(pstate, parent, stmt->partbound);
1114 
1115  /*
1116  * Check first that the new partition's bound is valid and does not
1117  * overlap with any of existing partitions of the parent.
1118  */
1119  check_new_partition_bound(relname, parent, bound, pstate);
1120 
1121  /*
1122  * If the default partition exists, its partition constraints will
1123  * change after the addition of this new partition such that it won't
1124  * allow any row that qualifies for this new partition. So, check that
1125  * the existing data in the default partition satisfies the constraint
1126  * as it will exist after adding this partition.
1127  */
1128  if (OidIsValid(defaultPartOid))
1129  {
1130  check_default_partition_contents(parent, defaultRel, bound);
1131  /* Keep the lock until commit. */
1132  table_close(defaultRel, NoLock);
1133  }
1134 
1135  /* Update the pg_class entry. */
1136  StorePartitionBound(rel, parent, bound);
1137 
1138  table_close(parent, NoLock);
1139  }
1140 
1141  /* Store inheritance information for new rel. */
1142  StoreCatalogInheritance(relationId, inheritOids, stmt->partbound != NULL);
1143 
1144  /*
1145  * Process the partitioning specification (if any) and store the partition
1146  * key information into the catalog.
1147  */
1148  if (partitioned)
1149  {
1150  ParseState *pstate;
1151  int partnatts;
1152  AttrNumber partattrs[PARTITION_MAX_KEYS];
1153  Oid partopclass[PARTITION_MAX_KEYS];
1154  Oid partcollation[PARTITION_MAX_KEYS];
1155  List *partexprs = NIL;
1156 
1157  pstate = make_parsestate(NULL);
1158  pstate->p_sourcetext = queryString;
1159 
1160  partnatts = list_length(stmt->partspec->partParams);
1161 
1162  /* Protect fixed-size arrays here and in executor */
1163  if (partnatts > PARTITION_MAX_KEYS)
1164  ereport(ERROR,
1165  (errcode(ERRCODE_TOO_MANY_COLUMNS),
1166  errmsg("cannot partition using more than %d columns",
1167  PARTITION_MAX_KEYS)));
1168 
1169  /*
1170  * We need to transform the raw parsetrees corresponding to partition
1171  * expressions into executable expression trees. Like column defaults
1172  * and CHECK constraints, we could not have done the transformation
1173  * earlier.
1174  */
1175  stmt->partspec = transformPartitionSpec(rel, stmt->partspec);
1176 
1177  ComputePartitionAttrs(pstate, rel, stmt->partspec->partParams,
1178  partattrs, &partexprs, partopclass,
1179  partcollation, stmt->partspec->strategy);
1180 
1181  StorePartitionKey(rel, stmt->partspec->strategy, partnatts, partattrs,
1182  partexprs,
1183  partopclass, partcollation);
1184 
1185  /* make it all visible */
1187  }
1188 
1189  /*
1190  * If we're creating a partition, create now all the indexes, triggers,
1191  * FKs defined in the parent.
1192  *
1193  * We can't do it earlier, because DefineIndex wants to know the partition
1194  * key which we just stored.
1195  */
1196  if (stmt->partbound)
1197  {
1198  Oid parentId = linitial_oid(inheritOids);
1199  Relation parent;
1200  List *idxlist;
1201  ListCell *cell;
1202 
1203  /* Already have strong enough lock on the parent */
1204  parent = table_open(parentId, NoLock);
1205  idxlist = RelationGetIndexList(parent);
1206 
1207  /*
1208  * For each index in the parent table, create one in the partition
1209  */
1210  foreach(cell, idxlist)
1211  {
1212  Relation idxRel = index_open(lfirst_oid(cell), AccessShareLock);
1213  AttrMap *attmap;
1214  IndexStmt *idxstmt;
1215  Oid constraintOid;
1216 
1217  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1218  {
1219  if (idxRel->rd_index->indisunique)
1220  ereport(ERROR,
1221  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1222  errmsg("cannot create foreign partition of partitioned table \"%s\"",
1223  RelationGetRelationName(parent)),
1224  errdetail("Table \"%s\" contains indexes that are unique.",
1225  RelationGetRelationName(parent))));
1226  else
1227  {
1228  index_close(idxRel, AccessShareLock);
1229  continue;
1230  }
1231  }
1232 
1234  RelationGetDescr(parent),
1235  false);
1236  idxstmt =
1237  generateClonedIndexStmt(NULL, idxRel,
1238  attmap, &constraintOid);
1240  idxstmt,
1241  InvalidOid,
1242  RelationGetRelid(idxRel),
1243  constraintOid,
1244  -1,
1245  false, false, false, false, false);
1246 
1247  index_close(idxRel, AccessShareLock);
1248  }
1249 
1250  list_free(idxlist);
1251 
1252  /*
1253  * If there are any row-level triggers, clone them to the new
1254  * partition.
1255  */
1256  if (parent->trigdesc != NULL)
1257  CloneRowTriggersToPartition(parent, rel);
1258 
1259  /*
1260  * And foreign keys too. Note that because we're freshly creating the
1261  * table, there is no need to verify these new constraints.
1262  */
1263  CloneForeignKeyConstraints(NULL, parent, rel);
1264 
1265  table_close(parent, NoLock);
1266  }
1267 
1268  /*
1269  * Now add any newly specified CHECK constraints to the new relation. Same
1270  * as for defaults above, but these need to come after partitioning is set
1271  * up.
1272  */
1273  if (stmt->constraints)
1274  AddRelationNewConstraints(rel, NIL, stmt->constraints,
1275  true, true, false, queryString);
1276 
1277  /*
1278  * Finally, merge the not-null constraints that are declared directly with
1279  * those that come from parent relations (making sure to count inheritance
1280  * appropriately for each), create them, and set the attnotnull flag on
1281  * columns that don't yet have it.
1282  */
1283  nncols = AddRelationNotNullConstraints(rel, stmt->nnconstraints,
1284  old_notnulls);
1285  foreach(listptr, nncols)
1286  set_attnotnull(NULL, rel, lfirst_int(listptr), false, NoLock);
1287 
1288  ObjectAddressSet(address, RelationRelationId, relationId);
1289 
1290  /*
1291  * Clean up. We keep lock on new relation (although it shouldn't be
1292  * visible to anyone else anyway, until commit).
1293  */
1294  relation_close(rel, NoLock);
1295 
1296  return address;
1297 }
1298 
1299 /*
1300  * BuildDescForRelation
1301  *
1302  * Given a list of ColumnDef nodes, build a TupleDesc.
1303  *
1304  * Note: tdtypeid will need to be filled in later on.
1305  */
1306 TupleDesc
1308 {
1309  int natts;
1311  ListCell *l;
1312  TupleDesc desc;
1313  bool has_not_null;
1314  char *attname;
1315  Oid atttypid;
1316  int32 atttypmod;
1317  Oid attcollation;
1318  int attdim;
1319 
1320  /*
1321  * allocate a new tuple descriptor
1322  */
1323  natts = list_length(columns);
1324  desc = CreateTemplateTupleDesc(natts);
1325  has_not_null = false;
1326 
1327  attnum = 0;
1328 
1329  foreach(l, columns)
1330  {
1331  ColumnDef *entry = lfirst(l);
1332  AclResult aclresult;
1333  Form_pg_attribute att;
1334 
1335  /*
1336  * for each entry in the list, get the name and type information from
1337  * the list and have TupleDescInitEntry fill in the attribute
1338  * information we need.
1339  */
1340  attnum++;
1341 
1342  attname = entry->colname;
1343  typenameTypeIdAndMod(NULL, entry->typeName, &atttypid, &atttypmod);
1344 
1345  aclresult = object_aclcheck(TypeRelationId, atttypid, GetUserId(), ACL_USAGE);
1346  if (aclresult != ACLCHECK_OK)
1347  aclcheck_error_type(aclresult, atttypid);
1348 
1349  attcollation = GetColumnDefCollation(NULL, entry, atttypid);
1350  attdim = list_length(entry->typeName->arrayBounds);
1351  if (attdim > PG_INT16_MAX)
1352  ereport(ERROR,
1353  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1354  errmsg("too many array dimensions"));
1355 
1356  if (entry->typeName->setof)
1357  ereport(ERROR,
1358  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
1359  errmsg("column \"%s\" cannot be declared SETOF",
1360  attname)));
1361 
1363  atttypid, atttypmod, attdim);
1364  att = TupleDescAttr(desc, attnum - 1);
1365 
1366  /* Override TupleDescInitEntry's settings as requested */
1367  TupleDescInitEntryCollation(desc, attnum, attcollation);
1368 
1369  /* Fill in additional stuff not handled by TupleDescInitEntry */
1370  att->attnotnull = entry->is_not_null;
1371  has_not_null |= entry->is_not_null;
1372  att->attislocal = entry->is_local;
1373  att->attinhcount = entry->inhcount;
1374  att->attidentity = entry->identity;
1375  att->attgenerated = entry->generated;
1376  att->attcompression = GetAttributeCompression(att->atttypid, entry->compression);
1377  if (entry->storage)
1378  att->attstorage = entry->storage;
1379  else if (entry->storage_name)
1380  att->attstorage = GetAttributeStorage(att->atttypid, entry->storage_name);
1381  }
1382 
1383  if (has_not_null)
1384  {
1385  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
1386 
1387  constr->has_not_null = true;
1388  constr->has_generated_stored = false;
1389  constr->defval = NULL;
1390  constr->missing = NULL;
1391  constr->num_defval = 0;
1392  constr->check = NULL;
1393  constr->num_check = 0;
1394  desc->constr = constr;
1395  }
1396  else
1397  {
1398  desc->constr = NULL;
1399  }
1400 
1401  return desc;
1402 }
1403 
1404 /*
1405  * Emit the right error or warning message for a "DROP" command issued on a
1406  * non-existent relation
1407  */
1408 static void
1409 DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
1410 {
1411  const struct dropmsgstrings *rentry;
1412 
1413  if (rel->schemaname != NULL &&
1415  {
1416  if (!missing_ok)
1417  {
1418  ereport(ERROR,
1419  (errcode(ERRCODE_UNDEFINED_SCHEMA),
1420  errmsg("schema \"%s\" does not exist", rel->schemaname)));
1421  }
1422  else
1423  {
1424  ereport(NOTICE,
1425  (errmsg("schema \"%s\" does not exist, skipping",
1426  rel->schemaname)));
1427  }
1428  return;
1429  }
1430 
1431  for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
1432  {
1433  if (rentry->kind == rightkind)
1434  {
1435  if (!missing_ok)
1436  {
1437  ereport(ERROR,
1438  (errcode(rentry->nonexistent_code),
1439  errmsg(rentry->nonexistent_msg, rel->relname)));
1440  }
1441  else
1442  {
1443  ereport(NOTICE, (errmsg(rentry->skipping_msg, rel->relname)));
1444  break;
1445  }
1446  }
1447  }
1448 
1449  Assert(rentry->kind != '\0'); /* Should be impossible */
1450 }
1451 
1452 /*
1453  * Emit the right error message for a "DROP" command issued on a
1454  * relation of the wrong type
1455  */
1456 static void
1457 DropErrorMsgWrongType(const char *relname, char wrongkind, char rightkind)
1458 {
1459  const struct dropmsgstrings *rentry;
1460  const struct dropmsgstrings *wentry;
1461 
1462  for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
1463  if (rentry->kind == rightkind)
1464  break;
1465  Assert(rentry->kind != '\0');
1466 
1467  for (wentry = dropmsgstringarray; wentry->kind != '\0'; wentry++)
1468  if (wentry->kind == wrongkind)
1469  break;
1470  /* wrongkind could be something we don't have in our table... */
1471 
1472  ereport(ERROR,
1473  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1474  errmsg(rentry->nota_msg, relname),
1475  (wentry->kind != '\0') ? errhint("%s", _(wentry->drophint_msg)) : 0));
1476 }
1477 
1478 /*
1479  * RemoveRelations
1480  * Implements DROP TABLE, DROP INDEX, DROP SEQUENCE, DROP VIEW,
1481  * DROP MATERIALIZED VIEW, DROP FOREIGN TABLE
1482  */
1483 void
1485 {
1486  ObjectAddresses *objects;
1487  char relkind;
1488  ListCell *cell;
1489  int flags = 0;
1490  LOCKMODE lockmode = AccessExclusiveLock;
1491 
1492  /* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */
1493  if (drop->concurrent)
1494  {
1495  /*
1496  * Note that for temporary relations this lock may get upgraded later
1497  * on, but as no other session can access a temporary relation, this
1498  * is actually fine.
1499  */
1500  lockmode = ShareUpdateExclusiveLock;
1501  Assert(drop->removeType == OBJECT_INDEX);
1502  if (list_length(drop->objects) != 1)
1503  ereport(ERROR,
1504  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1505  errmsg("DROP INDEX CONCURRENTLY does not support dropping multiple objects")));
1506  if (drop->behavior == DROP_CASCADE)
1507  ereport(ERROR,
1508  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1509  errmsg("DROP INDEX CONCURRENTLY does not support CASCADE")));
1510  }
1511 
1512  /*
1513  * First we identify all the relations, then we delete them in a single
1514  * performMultipleDeletions() call. This is to avoid unwanted DROP
1515  * RESTRICT errors if one of the relations depends on another.
1516  */
1517 
1518  /* Determine required relkind */
1519  switch (drop->removeType)
1520  {
1521  case OBJECT_TABLE:
1522  relkind = RELKIND_RELATION;
1523  break;
1524 
1525  case OBJECT_INDEX:
1526  relkind = RELKIND_INDEX;
1527  break;
1528 
1529  case OBJECT_SEQUENCE:
1530  relkind = RELKIND_SEQUENCE;
1531  break;
1532 
1533  case OBJECT_VIEW:
1534  relkind = RELKIND_VIEW;
1535  break;
1536 
1537  case OBJECT_MATVIEW:
1538  relkind = RELKIND_MATVIEW;
1539  break;
1540 
1541  case OBJECT_FOREIGN_TABLE:
1542  relkind = RELKIND_FOREIGN_TABLE;
1543  break;
1544 
1545  default:
1546  elog(ERROR, "unrecognized drop object type: %d",
1547  (int) drop->removeType);
1548  relkind = 0; /* keep compiler quiet */
1549  break;
1550  }
1551 
1552  /* Lock and validate each relation; build a list of object addresses */
1553  objects = new_object_addresses();
1554 
1555  foreach(cell, drop->objects)
1556  {
1557  RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell));
1558  Oid relOid;
1559  ObjectAddress obj;
1561 
1562  /*
1563  * These next few steps are a great deal like relation_openrv, but we
1564  * don't bother building a relcache entry since we don't need it.
1565  *
1566  * Check for shared-cache-inval messages before trying to access the
1567  * relation. This is needed to cover the case where the name
1568  * identifies a rel that has been dropped and recreated since the
1569  * start of our transaction: if we don't flush the old syscache entry,
1570  * then we'll latch onto that entry and suffer an error later.
1571  */
1573 
1574  /* Look up the appropriate relation using namespace search. */
1575  state.expected_relkind = relkind;
1576  state.heap_lockmode = drop->concurrent ?
1578  /* We must initialize these fields to show that no locks are held: */
1579  state.heapOid = InvalidOid;
1580  state.partParentOid = InvalidOid;
1581 
1582  relOid = RangeVarGetRelidExtended(rel, lockmode, RVR_MISSING_OK,
1584  (void *) &state);
1585 
1586  /* Not there? */
1587  if (!OidIsValid(relOid))
1588  {
1589  DropErrorMsgNonExistent(rel, relkind, drop->missing_ok);
1590  continue;
1591  }
1592 
1593  /*
1594  * Decide if concurrent mode needs to be used here or not. The
1595  * callback retrieved the rel's persistence for us.
1596  */
1597  if (drop->concurrent &&
1598  state.actual_relpersistence != RELPERSISTENCE_TEMP)
1599  {
1600  Assert(list_length(drop->objects) == 1 &&
1601  drop->removeType == OBJECT_INDEX);
1603  }
1604 
1605  /*
1606  * Concurrent index drop cannot be used with partitioned indexes,
1607  * either.
1608  */
1609  if ((flags & PERFORM_DELETION_CONCURRENTLY) != 0 &&
1610  state.actual_relkind == RELKIND_PARTITIONED_INDEX)
1611  ereport(ERROR,
1612  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1613  errmsg("cannot drop partitioned index \"%s\" concurrently",
1614  rel->relname)));
1615 
1616  /*
1617  * If we're told to drop a partitioned index, we must acquire lock on
1618  * all the children of its parent partitioned table before proceeding.
1619  * Otherwise we'd try to lock the child index partitions before their
1620  * tables, leading to potential deadlock against other sessions that
1621  * will lock those objects in the other order.
1622  */
1623  if (state.actual_relkind == RELKIND_PARTITIONED_INDEX)
1624  (void) find_all_inheritors(state.heapOid,
1625  state.heap_lockmode,
1626  NULL);
1627 
1628  /* OK, we're ready to delete this one */
1629  obj.classId = RelationRelationId;
1630  obj.objectId = relOid;
1631  obj.objectSubId = 0;
1632 
1633  add_exact_object_address(&obj, objects);
1634  }
1635 
1636  performMultipleDeletions(objects, drop->behavior, flags);
1637 
1638  free_object_addresses(objects);
1639 }
1640 
1641 /*
1642  * Before acquiring a table lock, check whether we have sufficient rights.
1643  * In the case of DROP INDEX, also try to lock the table before the index.
1644  * Also, if the table to be dropped is a partition, we try to lock the parent
1645  * first.
1646  */
1647 static void
1648 RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
1649  void *arg)
1650 {
1651  HeapTuple tuple;
1653  char expected_relkind;
1654  bool is_partition;
1655  Form_pg_class classform;
1657  bool invalid_system_index = false;
1658 
1659  state = (struct DropRelationCallbackState *) arg;
1660  heap_lockmode = state->heap_lockmode;
1661 
1662  /*
1663  * If we previously locked some other index's heap, and the name we're
1664  * looking up no longer refers to that relation, release the now-useless
1665  * lock.
1666  */
1667  if (relOid != oldRelOid && OidIsValid(state->heapOid))
1668  {
1670  state->heapOid = InvalidOid;
1671  }
1672 
1673  /*
1674  * Similarly, if we previously locked some other partition's heap, and the
1675  * name we're looking up no longer refers to that relation, release the
1676  * now-useless lock.
1677  */
1678  if (relOid != oldRelOid && OidIsValid(state->partParentOid))
1679  {
1680  UnlockRelationOid(state->partParentOid, AccessExclusiveLock);
1681  state->partParentOid = InvalidOid;
1682  }
1683 
1684  /* Didn't find a relation, so no need for locking or permission checks. */
1685  if (!OidIsValid(relOid))
1686  return;
1687 
1688  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
1689  if (!HeapTupleIsValid(tuple))
1690  return; /* concurrently dropped, so nothing to do */
1691  classform = (Form_pg_class) GETSTRUCT(tuple);
1692  is_partition = classform->relispartition;
1693 
1694  /* Pass back some data to save lookups in RemoveRelations */
1695  state->actual_relkind = classform->relkind;
1696  state->actual_relpersistence = classform->relpersistence;
1697 
1698  /*
1699  * Both RELKIND_RELATION and RELKIND_PARTITIONED_TABLE are OBJECT_TABLE,
1700  * but RemoveRelations() can only pass one relkind for a given relation.
1701  * It chooses RELKIND_RELATION for both regular and partitioned tables.
1702  * That means we must be careful before giving the wrong type error when
1703  * the relation is RELKIND_PARTITIONED_TABLE. An equivalent problem
1704  * exists with indexes.
1705  */
1706  if (classform->relkind == RELKIND_PARTITIONED_TABLE)
1707  expected_relkind = RELKIND_RELATION;
1708  else if (classform->relkind == RELKIND_PARTITIONED_INDEX)
1709  expected_relkind = RELKIND_INDEX;
1710  else
1711  expected_relkind = classform->relkind;
1712 
1713  if (state->expected_relkind != expected_relkind)
1714  DropErrorMsgWrongType(rel->relname, classform->relkind,
1715  state->expected_relkind);
1716 
1717  /* Allow DROP to either table owner or schema owner */
1718  if (!object_ownercheck(RelationRelationId, relOid, GetUserId()) &&
1719  !object_ownercheck(NamespaceRelationId, classform->relnamespace, GetUserId()))
1721  get_relkind_objtype(classform->relkind),
1722  rel->relname);
1723 
1724  /*
1725  * Check the case of a system index that might have been invalidated by a
1726  * failed concurrent process and allow its drop. For the time being, this
1727  * only concerns indexes of toast relations that became invalid during a
1728  * REINDEX CONCURRENTLY process.
1729  */
1730  if (IsSystemClass(relOid, classform) && classform->relkind == RELKIND_INDEX)
1731  {
1732  HeapTuple locTuple;
1733  Form_pg_index indexform;
1734  bool indisvalid;
1735 
1736  locTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(relOid));
1737  if (!HeapTupleIsValid(locTuple))
1738  {
1739  ReleaseSysCache(tuple);
1740  return;
1741  }
1742 
1743  indexform = (Form_pg_index) GETSTRUCT(locTuple);
1744  indisvalid = indexform->indisvalid;
1745  ReleaseSysCache(locTuple);
1746 
1747  /* Mark object as being an invalid index of system catalogs */
1748  if (!indisvalid)
1749  invalid_system_index = true;
1750  }
1751 
1752  /* In the case of an invalid index, it is fine to bypass this check */
1753  if (!invalid_system_index && !allowSystemTableMods && IsSystemClass(relOid, classform))
1754  ereport(ERROR,
1755  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1756  errmsg("permission denied: \"%s\" is a system catalog",
1757  rel->relname)));
1758 
1759  ReleaseSysCache(tuple);
1760 
1761  /*
1762  * In DROP INDEX, attempt to acquire lock on the parent table before
1763  * locking the index. index_drop() will need this anyway, and since
1764  * regular queries lock tables before their indexes, we risk deadlock if
1765  * we do it the other way around. No error if we don't find a pg_index
1766  * entry, though --- the relation may have been dropped. Note that this
1767  * code will execute for either plain or partitioned indexes.
1768  */
1769  if (expected_relkind == RELKIND_INDEX &&
1770  relOid != oldRelOid)
1771  {
1772  state->heapOid = IndexGetRelation(relOid, true);
1773  if (OidIsValid(state->heapOid))
1774  LockRelationOid(state->heapOid, heap_lockmode);
1775  }
1776 
1777  /*
1778  * Similarly, if the relation is a partition, we must acquire lock on its
1779  * parent before locking the partition. That's because queries lock the
1780  * parent before its partitions, so we risk deadlock if we do it the other
1781  * way around.
1782  */
1783  if (is_partition && relOid != oldRelOid)
1784  {
1785  state->partParentOid = get_partition_parent(relOid, true);
1786  if (OidIsValid(state->partParentOid))
1787  LockRelationOid(state->partParentOid, AccessExclusiveLock);
1788  }
1789 }
1790 
1791 /*
1792  * ExecuteTruncate
1793  * Executes a TRUNCATE command.
1794  *
1795  * This is a multi-relation truncate. We first open and grab exclusive
1796  * lock on all relations involved, checking permissions and otherwise
1797  * verifying that the relation is OK for truncation. Note that if relations
1798  * are foreign tables, at this stage, we have not yet checked that their
1799  * foreign data in external data sources are OK for truncation. These are
1800  * checked when foreign data are actually truncated later. In CASCADE mode,
1801  * relations having FK references to the targeted relations are automatically
1802  * added to the group; in RESTRICT mode, we check that all FK references are
1803  * internal to the group that's being truncated. Finally all the relations
1804  * are truncated and reindexed.
1805  */
1806 void
1808 {
1809  List *rels = NIL;
1810  List *relids = NIL;
1811  List *relids_logged = NIL;
1812  ListCell *cell;
1813 
1814  /*
1815  * Open, exclusive-lock, and check all the explicitly-specified relations
1816  */
1817  foreach(cell, stmt->relations)
1818  {
1819  RangeVar *rv = lfirst(cell);
1820  Relation rel;
1821  bool recurse = rv->inh;
1822  Oid myrelid;
1823  LOCKMODE lockmode = AccessExclusiveLock;
1824 
1825  myrelid = RangeVarGetRelidExtended(rv, lockmode,
1827  NULL);
1828 
1829  /* don't throw error for "TRUNCATE foo, foo" */
1830  if (list_member_oid(relids, myrelid))
1831  continue;
1832 
1833  /* open the relation, we already hold a lock on it */
1834  rel = table_open(myrelid, NoLock);
1835 
1836  /*
1837  * RangeVarGetRelidExtended() has done most checks with its callback,
1838  * but other checks with the now-opened Relation remain.
1839  */
1841 
1842  rels = lappend(rels, rel);
1843  relids = lappend_oid(relids, myrelid);
1844 
1845  /* Log this relation only if needed for logical decoding */
1846  if (RelationIsLogicallyLogged(rel))
1847  relids_logged = lappend_oid(relids_logged, myrelid);
1848 
1849  if (recurse)
1850  {
1851  ListCell *child;
1852  List *children;
1853 
1854  children = find_all_inheritors(myrelid, lockmode, NULL);
1855 
1856  foreach(child, children)
1857  {
1858  Oid childrelid = lfirst_oid(child);
1859 
1860  if (list_member_oid(relids, childrelid))
1861  continue;
1862 
1863  /* find_all_inheritors already got lock */
1864  rel = table_open(childrelid, NoLock);
1865 
1866  /*
1867  * It is possible that the parent table has children that are
1868  * temp tables of other backends. We cannot safely access
1869  * such tables (because of buffering issues), and the best
1870  * thing to do is to silently ignore them. Note that this
1871  * check is the same as one of the checks done in
1872  * truncate_check_activity() called below, still it is kept
1873  * here for simplicity.
1874  */
1875  if (RELATION_IS_OTHER_TEMP(rel))
1876  {
1877  table_close(rel, lockmode);
1878  continue;
1879  }
1880 
1881  /*
1882  * Inherited TRUNCATE commands perform access permission
1883  * checks on the parent table only. So we skip checking the
1884  * children's permissions and don't call
1885  * truncate_check_perms() here.
1886  */
1889 
1890  rels = lappend(rels, rel);
1891  relids = lappend_oid(relids, childrelid);
1892 
1893  /* Log this relation only if needed for logical decoding */
1894  if (RelationIsLogicallyLogged(rel))
1895  relids_logged = lappend_oid(relids_logged, childrelid);
1896  }
1897  }
1898  else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1899  ereport(ERROR,
1900  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1901  errmsg("cannot truncate only a partitioned table"),
1902  errhint("Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly.")));
1903  }
1904 
1905  ExecuteTruncateGuts(rels, relids, relids_logged,
1906  stmt->behavior, stmt->restart_seqs, false);
1907 
1908  /* And close the rels */
1909  foreach(cell, rels)
1910  {
1911  Relation rel = (Relation) lfirst(cell);
1912 
1913  table_close(rel, NoLock);
1914  }
1915 }
1916 
1917 /*
1918  * ExecuteTruncateGuts
1919  *
1920  * Internal implementation of TRUNCATE. This is called by the actual TRUNCATE
1921  * command (see above) as well as replication subscribers that execute a
1922  * replicated TRUNCATE action.
1923  *
1924  * explicit_rels is the list of Relations to truncate that the command
1925  * specified. relids is the list of Oids corresponding to explicit_rels.
1926  * relids_logged is the list of Oids (a subset of relids) that require
1927  * WAL-logging. This is all a bit redundant, but the existing callers have
1928  * this information handy in this form.
1929  */
1930 void
1931 ExecuteTruncateGuts(List *explicit_rels,
1932  List *relids,
1933  List *relids_logged,
1934  DropBehavior behavior, bool restart_seqs,
1935  bool run_as_table_owner)
1936 {
1937  List *rels;
1938  List *seq_relids = NIL;
1939  HTAB *ft_htab = NULL;
1940  EState *estate;
1941  ResultRelInfo *resultRelInfos;
1942  ResultRelInfo *resultRelInfo;
1943  SubTransactionId mySubid;
1944  ListCell *cell;
1945  Oid *logrelids;
1946 
1947  /*
1948  * Check the explicitly-specified relations.
1949  *
1950  * In CASCADE mode, suck in all referencing relations as well. This
1951  * requires multiple iterations to find indirectly-dependent relations. At
1952  * each phase, we need to exclusive-lock new rels before looking for their
1953  * dependencies, else we might miss something. Also, we check each rel as
1954  * soon as we open it, to avoid a faux pas such as holding lock for a long
1955  * time on a rel we have no permissions for.
1956  */
1957  rels = list_copy(explicit_rels);
1958  if (behavior == DROP_CASCADE)
1959  {
1960  for (;;)
1961  {
1962  List *newrelids;
1963 
1964  newrelids = heap_truncate_find_FKs(relids);
1965  if (newrelids == NIL)
1966  break; /* nothing else to add */
1967 
1968  foreach(cell, newrelids)
1969  {
1970  Oid relid = lfirst_oid(cell);
1971  Relation rel;
1972 
1973  rel = table_open(relid, AccessExclusiveLock);
1974  ereport(NOTICE,
1975  (errmsg("truncate cascades to table \"%s\"",
1976  RelationGetRelationName(rel))));
1977  truncate_check_rel(relid, rel->rd_rel);
1978  truncate_check_perms(relid, rel->rd_rel);
1980  rels = lappend(rels, rel);
1981  relids = lappend_oid(relids, relid);
1982 
1983  /* Log this relation only if needed for logical decoding */
1984  if (RelationIsLogicallyLogged(rel))
1985  relids_logged = lappend_oid(relids_logged, relid);
1986  }
1987  }
1988  }
1989 
1990  /*
1991  * Check foreign key references. In CASCADE mode, this should be
1992  * unnecessary since we just pulled in all the references; but as a
1993  * cross-check, do it anyway if in an Assert-enabled build.
1994  */
1995 #ifdef USE_ASSERT_CHECKING
1996  heap_truncate_check_FKs(rels, false);
1997 #else
1998  if (behavior == DROP_RESTRICT)
1999  heap_truncate_check_FKs(rels, false);
2000 #endif
2001 
2002  /*
2003  * If we are asked to restart sequences, find all the sequences, lock them
2004  * (we need AccessExclusiveLock for ResetSequence), and check permissions.
2005  * We want to do this early since it's pointless to do all the truncation
2006  * work only to fail on sequence permissions.
2007  */
2008  if (restart_seqs)
2009  {
2010  foreach(cell, rels)
2011  {
2012  Relation rel = (Relation) lfirst(cell);
2013  List *seqlist = getOwnedSequences(RelationGetRelid(rel));
2014  ListCell *seqcell;
2015 
2016  foreach(seqcell, seqlist)
2017  {
2018  Oid seq_relid = lfirst_oid(seqcell);
2019  Relation seq_rel;
2020 
2021  seq_rel = relation_open(seq_relid, AccessExclusiveLock);
2022 
2023  /* This check must match AlterSequence! */
2024  if (!object_ownercheck(RelationRelationId, seq_relid, GetUserId()))
2026  RelationGetRelationName(seq_rel));
2027 
2028  seq_relids = lappend_oid(seq_relids, seq_relid);
2029 
2030  relation_close(seq_rel, NoLock);
2031  }
2032  }
2033  }
2034 
2035  /* Prepare to catch AFTER triggers. */
2037 
2038  /*
2039  * To fire triggers, we'll need an EState as well as a ResultRelInfo for
2040  * each relation. We don't need to call ExecOpenIndices, though.
2041  *
2042  * We put the ResultRelInfos in the es_opened_result_relations list, even
2043  * though we don't have a range table and don't populate the
2044  * es_result_relations array. That's a bit bogus, but it's enough to make
2045  * ExecGetTriggerResultRel() find them.
2046  */
2047  estate = CreateExecutorState();
2048  resultRelInfos = (ResultRelInfo *)
2049  palloc(list_length(rels) * sizeof(ResultRelInfo));
2050  resultRelInfo = resultRelInfos;
2051  foreach(cell, rels)
2052  {
2053  Relation rel = (Relation) lfirst(cell);
2054 
2055  InitResultRelInfo(resultRelInfo,
2056  rel,
2057  0, /* dummy rangetable index */
2058  NULL,
2059  0);
2060  estate->es_opened_result_relations =
2061  lappend(estate->es_opened_result_relations, resultRelInfo);
2062  resultRelInfo++;
2063  }
2064 
2065  /*
2066  * Process all BEFORE STATEMENT TRUNCATE triggers before we begin
2067  * truncating (this is because one of them might throw an error). Also, if
2068  * we were to allow them to prevent statement execution, that would need
2069  * to be handled here.
2070  */
2071  resultRelInfo = resultRelInfos;
2072  foreach(cell, rels)
2073  {
2074  UserContext ucxt;
2075 
2076  if (run_as_table_owner)
2077  SwitchToUntrustedUser(resultRelInfo->ri_RelationDesc->rd_rel->relowner,
2078  &ucxt);
2079  ExecBSTruncateTriggers(estate, resultRelInfo);
2080  if (run_as_table_owner)
2081  RestoreUserContext(&ucxt);
2082  resultRelInfo++;
2083  }
2084 
2085  /*
2086  * OK, truncate each table.
2087  */
2088  mySubid = GetCurrentSubTransactionId();
2089 
2090  foreach(cell, rels)
2091  {
2092  Relation rel = (Relation) lfirst(cell);
2093 
2094  /* Skip partitioned tables as there is nothing to do */
2095  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
2096  continue;
2097 
2098  /*
2099  * Build the lists of foreign tables belonging to each foreign server
2100  * and pass each list to the foreign data wrapper's callback function,
2101  * so that each server can truncate its all foreign tables in bulk.
2102  * Each list is saved as a single entry in a hash table that uses the
2103  * server OID as lookup key.
2104  */
2105  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
2106  {
2108  bool found;
2109  ForeignTruncateInfo *ft_info;
2110 
2111  /* First time through, initialize hashtable for foreign tables */
2112  if (!ft_htab)
2113  {
2114  HASHCTL hctl;
2115 
2116  memset(&hctl, 0, sizeof(HASHCTL));
2117  hctl.keysize = sizeof(Oid);
2118  hctl.entrysize = sizeof(ForeignTruncateInfo);
2119  hctl.hcxt = CurrentMemoryContext;
2120 
2121  ft_htab = hash_create("TRUNCATE for Foreign Tables",
2122  32, /* start small and extend */
2123  &hctl,
2125  }
2126 
2127  /* Find or create cached entry for the foreign table */
2128  ft_info = hash_search(ft_htab, &serverid, HASH_ENTER, &found);
2129  if (!found)
2130  ft_info->rels = NIL;
2131 
2132  /*
2133  * Save the foreign table in the entry of the server that the
2134  * foreign table belongs to.
2135  */
2136  ft_info->rels = lappend(ft_info->rels, rel);
2137  continue;
2138  }
2139 
2140  /*
2141  * Normally, we need a transaction-safe truncation here. However, if
2142  * the table was either created in the current (sub)transaction or has
2143  * a new relfilenumber in the current (sub)transaction, then we can
2144  * just truncate it in-place, because a rollback would cause the whole
2145  * table or the current physical file to be thrown away anyway.
2146  */
2147  if (rel->rd_createSubid == mySubid ||
2148  rel->rd_newRelfilelocatorSubid == mySubid)
2149  {
2150  /* Immediate, non-rollbackable truncation is OK */
2151  heap_truncate_one_rel(rel);
2152  }
2153  else
2154  {
2155  Oid heap_relid;
2156  Oid toast_relid;
2157  ReindexParams reindex_params = {0};
2158 
2159  /*
2160  * This effectively deletes all rows in the table, and may be done
2161  * in a serializable transaction. In that case we must record a
2162  * rw-conflict in to this transaction from each transaction
2163  * holding a predicate lock on the table.
2164  */
2166 
2167  /*
2168  * Need the full transaction-safe pushups.
2169  *
2170  * Create a new empty storage file for the relation, and assign it
2171  * as the relfilenumber value. The old storage file is scheduled
2172  * for deletion at commit.
2173  */
2174  RelationSetNewRelfilenumber(rel, rel->rd_rel->relpersistence);
2175 
2176  heap_relid = RelationGetRelid(rel);
2177 
2178  /*
2179  * The same for the toast table, if any.
2180  */
2181  toast_relid = rel->rd_rel->reltoastrelid;
2182  if (OidIsValid(toast_relid))
2183  {
2184  Relation toastrel = relation_open(toast_relid,
2186 
2187  RelationSetNewRelfilenumber(toastrel,
2188  toastrel->rd_rel->relpersistence);
2189  table_close(toastrel, NoLock);
2190  }
2191 
2192  /*
2193  * Reconstruct the indexes to match, and we're done.
2194  */
2195  reindex_relation(NULL, heap_relid, REINDEX_REL_PROCESS_TOAST,
2196  &reindex_params);
2197  }
2198 
2199  pgstat_count_truncate(rel);
2200  }
2201 
2202  /* Now go through the hash table, and truncate foreign tables */
2203  if (ft_htab)
2204  {
2205  ForeignTruncateInfo *ft_info;
2206  HASH_SEQ_STATUS seq;
2207 
2208  hash_seq_init(&seq, ft_htab);
2209 
2210  PG_TRY();
2211  {
2212  while ((ft_info = hash_seq_search(&seq)) != NULL)
2213  {
2214  FdwRoutine *routine = GetFdwRoutineByServerId(ft_info->serverid);
2215 
2216  /* truncate_check_rel() has checked that already */
2217  Assert(routine->ExecForeignTruncate != NULL);
2218 
2219  routine->ExecForeignTruncate(ft_info->rels,
2220  behavior,
2221  restart_seqs);
2222  }
2223  }
2224  PG_FINALLY();
2225  {
2226  hash_destroy(ft_htab);
2227  }
2228  PG_END_TRY();
2229  }
2230 
2231  /*
2232  * Restart owned sequences if we were asked to.
2233  */
2234  foreach(cell, seq_relids)
2235  {
2236  Oid seq_relid = lfirst_oid(cell);
2237 
2238  ResetSequence(seq_relid);
2239  }
2240 
2241  /*
2242  * Write a WAL record to allow this set of actions to be logically
2243  * decoded.
2244  *
2245  * Assemble an array of relids so we can write a single WAL record for the
2246  * whole action.
2247  */
2248  if (relids_logged != NIL)
2249  {
2250  xl_heap_truncate xlrec;
2251  int i = 0;
2252 
2253  /* should only get here if wal_level >= logical */
2255 
2256  logrelids = palloc(list_length(relids_logged) * sizeof(Oid));
2257  foreach(cell, relids_logged)
2258  logrelids[i++] = lfirst_oid(cell);
2259 
2260  xlrec.dbId = MyDatabaseId;
2261  xlrec.nrelids = list_length(relids_logged);
2262  xlrec.flags = 0;
2263  if (behavior == DROP_CASCADE)
2264  xlrec.flags |= XLH_TRUNCATE_CASCADE;
2265  if (restart_seqs)
2267 
2268  XLogBeginInsert();
2269  XLogRegisterData((char *) &xlrec, SizeOfHeapTruncate);
2270  XLogRegisterData((char *) logrelids, list_length(relids_logged) * sizeof(Oid));
2271 
2273 
2274  (void) XLogInsert(RM_HEAP_ID, XLOG_HEAP_TRUNCATE);
2275  }
2276 
2277  /*
2278  * Process all AFTER STATEMENT TRUNCATE triggers.
2279  */
2280  resultRelInfo = resultRelInfos;
2281  foreach(cell, rels)
2282  {
2283  UserContext ucxt;
2284 
2285  if (run_as_table_owner)
2286  SwitchToUntrustedUser(resultRelInfo->ri_RelationDesc->rd_rel->relowner,
2287  &ucxt);
2288  ExecASTruncateTriggers(estate, resultRelInfo);
2289  if (run_as_table_owner)
2290  RestoreUserContext(&ucxt);
2291  resultRelInfo++;
2292  }
2293 
2294  /* Handle queued AFTER triggers */
2295  AfterTriggerEndQuery(estate);
2296 
2297  /* We can clean up the EState now */
2298  FreeExecutorState(estate);
2299 
2300  /*
2301  * Close any rels opened by CASCADE (can't do this while EState still
2302  * holds refs)
2303  */
2304  rels = list_difference_ptr(rels, explicit_rels);
2305  foreach(cell, rels)
2306  {
2307  Relation rel = (Relation) lfirst(cell);
2308 
2309  table_close(rel, NoLock);
2310  }
2311 }
2312 
2313 /*
2314  * Check that a given relation is safe to truncate. Subroutine for
2315  * ExecuteTruncate() and RangeVarCallbackForTruncate().
2316  */
2317 static void
2319 {
2320  char *relname = NameStr(reltuple->relname);
2321 
2322  /*
2323  * Only allow truncate on regular tables, foreign tables using foreign
2324  * data wrappers supporting TRUNCATE and partitioned tables (although, the
2325  * latter are only being included here for the following checks; no
2326  * physical truncation will occur in their case.).
2327  */
2328  if (reltuple->relkind == RELKIND_FOREIGN_TABLE)
2329  {
2330  Oid serverid = GetForeignServerIdByRelId(relid);
2331  FdwRoutine *fdwroutine = GetFdwRoutineByServerId(serverid);
2332 
2333  if (!fdwroutine->ExecForeignTruncate)
2334  ereport(ERROR,
2335  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2336  errmsg("cannot truncate foreign table \"%s\"",
2337  relname)));
2338  }
2339  else if (reltuple->relkind != RELKIND_RELATION &&
2340  reltuple->relkind != RELKIND_PARTITIONED_TABLE)
2341  ereport(ERROR,
2342  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2343  errmsg("\"%s\" is not a table", relname)));
2344 
2345  /*
2346  * Most system catalogs can't be truncated at all, or at least not unless
2347  * allow_system_table_mods=on. As an exception, however, we allow
2348  * pg_largeobject to be truncated as part of pg_upgrade, because we need
2349  * to change its relfilenode to match the old cluster, and allowing a
2350  * TRUNCATE command to be executed is the easiest way of doing that.
2351  */
2352  if (!allowSystemTableMods && IsSystemClass(relid, reltuple)
2353  && (!IsBinaryUpgrade || relid != LargeObjectRelationId))
2354  ereport(ERROR,
2355  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2356  errmsg("permission denied: \"%s\" is a system catalog",
2357  relname)));
2358 
2359  InvokeObjectTruncateHook(relid);
2360 }
2361 
2362 /*
2363  * Check that current user has the permission to truncate given relation.
2364  */
2365 static void
2367 {
2368  char *relname = NameStr(reltuple->relname);
2369  AclResult aclresult;
2370 
2371  /* Permissions checks */
2372  aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_TRUNCATE);
2373  if (aclresult != ACLCHECK_OK)
2374  aclcheck_error(aclresult, get_relkind_objtype(reltuple->relkind),
2375  relname);
2376 }
2377 
2378 /*
2379  * Set of extra sanity checks to check if a given relation is safe to
2380  * truncate. This is split with truncate_check_rel() as
2381  * RangeVarCallbackForTruncate() cannot open a Relation yet.
2382  */
2383 static void
2385 {
2386  /*
2387  * Don't allow truncate on temp tables of other backends ... their local
2388  * buffer manager is not going to cope.
2389  */
2390  if (RELATION_IS_OTHER_TEMP(rel))
2391  ereport(ERROR,
2392  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2393  errmsg("cannot truncate temporary tables of other sessions")));
2394 
2395  /*
2396  * Also check for active uses of the relation in the current transaction,
2397  * including open scans and pending AFTER trigger events.
2398  */
2399  CheckTableNotInUse(rel, "TRUNCATE");
2400 }
2401 
2402 /*
2403  * storage_name
2404  * returns the name corresponding to a typstorage/attstorage enum value
2405  */
2406 static const char *
2408 {
2409  switch (c)
2410  {
2411  case TYPSTORAGE_PLAIN:
2412  return "PLAIN";
2413  case TYPSTORAGE_EXTERNAL:
2414  return "EXTERNAL";
2415  case TYPSTORAGE_EXTENDED:
2416  return "EXTENDED";
2417  case TYPSTORAGE_MAIN:
2418  return "MAIN";
2419  default:
2420  return "???";
2421  }
2422 }
2423 
2424 /*----------
2425  * MergeAttributes
2426  * Returns new schema given initial schema and superclasses.
2427  *
2428  * Input arguments:
2429  * 'columns' is the column/attribute definition for the table. (It's a list
2430  * of ColumnDef's.) It is destructively changed.
2431  * 'supers' is a list of OIDs of parent relations, already locked by caller.
2432  * 'relpersistence' is the persistence type of the table.
2433  * 'is_partition' tells if the table is a partition.
2434  *
2435  * Output arguments:
2436  * 'supconstr' receives a list of constraints belonging to the parents,
2437  * updated as necessary to be valid for the child.
2438  * 'supnotnulls' receives a list of CookedConstraints that corresponds to
2439  * constraints coming from inheritance parents.
2440  *
2441  * Return value:
2442  * Completed schema list.
2443  *
2444  * Notes:
2445  * The order in which the attributes are inherited is very important.
2446  * Intuitively, the inherited attributes should come first. If a table
2447  * inherits from multiple parents, the order of those attributes are
2448  * according to the order of the parents specified in CREATE TABLE.
2449  *
2450  * Here's an example:
2451  *
2452  * create table person (name text, age int4, location point);
2453  * create table emp (salary int4, manager text) inherits(person);
2454  * create table student (gpa float8) inherits (person);
2455  * create table stud_emp (percent int4) inherits (emp, student);
2456  *
2457  * The order of the attributes of stud_emp is:
2458  *
2459  * person {1:name, 2:age, 3:location}
2460  * / \
2461  * {6:gpa} student emp {4:salary, 5:manager}
2462  * \ /
2463  * stud_emp {7:percent}
2464  *
2465  * If the same attribute name appears multiple times, then it appears
2466  * in the result table in the proper location for its first appearance.
2467  *
2468  * Constraints (including not-null constraints) for the child table
2469  * are the union of all relevant constraints, from both the child schema
2470  * and parent tables. In addition, in legacy inheritance, each column that
2471  * appears in a primary key in any of the parents also gets a NOT NULL
2472  * constraint (partitioning doesn't need this, because the PK itself gets
2473  * inherited.)
2474  *
2475  * The default value for a child column is defined as:
2476  * (1) If the child schema specifies a default, that value is used.
2477  * (2) If neither the child nor any parent specifies a default, then
2478  * the column will not have a default.
2479  * (3) If conflicting defaults are inherited from different parents
2480  * (and not overridden by the child), an error is raised.
2481  * (4) Otherwise the inherited default is used.
2482  *
2483  * Note that the default-value infrastructure is used for generated
2484  * columns' expressions too, so most of the preceding paragraph applies
2485  * to generation expressions too. We insist that a child column be
2486  * generated if and only if its parent(s) are, but it need not have
2487  * the same generation expression.
2488  *----------
2489  */
2490 static List *
2491 MergeAttributes(List *columns, const List *supers, char relpersistence,
2492  bool is_partition, List **supconstr, List **supnotnulls)
2493 {
2494  List *inh_columns = NIL;
2495  List *constraints = NIL;
2496  List *nnconstraints = NIL;
2497  bool have_bogus_defaults = false;
2498  int child_attno;
2499  static Node bogus_marker = {0}; /* marks conflicting defaults */
2500  List *saved_columns = NIL;
2501  ListCell *lc;
2502 
2503  /*
2504  * Check for and reject tables with too many columns. We perform this
2505  * check relatively early for two reasons: (a) we don't run the risk of
2506  * overflowing an AttrNumber in subsequent code (b) an O(n^2) algorithm is
2507  * okay if we're processing <= 1600 columns, but could take minutes to
2508  * execute if the user attempts to create a table with hundreds of
2509  * thousands of columns.
2510  *
2511  * Note that we also need to check that we do not exceed this figure after
2512  * including columns from inherited relations.
2513  */
2514  if (list_length(columns) > MaxHeapAttributeNumber)
2515  ereport(ERROR,
2516  (errcode(ERRCODE_TOO_MANY_COLUMNS),
2517  errmsg("tables can have at most %d columns",
2519 
2520  /*
2521  * Check for duplicate names in the explicit list of attributes.
2522  *
2523  * Although we might consider merging such entries in the same way that we
2524  * handle name conflicts for inherited attributes, it seems to make more
2525  * sense to assume such conflicts are errors.
2526  *
2527  * We don't use foreach() here because we have two nested loops over the
2528  * columns list, with possible element deletions in the inner one. If we
2529  * used foreach_delete_current() it could only fix up the state of one of
2530  * the loops, so it seems cleaner to use looping over list indexes for
2531  * both loops. Note that any deletion will happen beyond where the outer
2532  * loop is, so its index never needs adjustment.
2533  */
2534  for (int coldefpos = 0; coldefpos < list_length(columns); coldefpos++)
2535  {
2536  ColumnDef *coldef = list_nth_node(ColumnDef, columns, coldefpos);
2537 
2538  if (!is_partition && coldef->typeName == NULL)
2539  {
2540  /*
2541  * Typed table column option that does not belong to a column from
2542  * the type. This works because the columns from the type come
2543  * first in the list. (We omit this check for partition column
2544  * lists; those are processed separately below.)
2545  */
2546  ereport(ERROR,
2547  (errcode(ERRCODE_UNDEFINED_COLUMN),
2548  errmsg("column \"%s\" does not exist",
2549  coldef->colname)));
2550  }
2551 
2552  /* restpos scans all entries beyond coldef; incr is in loop body */
2553  for (int restpos = coldefpos + 1; restpos < list_length(columns);)
2554  {
2555  ColumnDef *restdef = list_nth_node(ColumnDef, columns, restpos);
2556 
2557  if (strcmp(coldef->colname, restdef->colname) == 0)
2558  {
2559  if (coldef->is_from_type)
2560  {
2561  /*
2562  * merge the column options into the column from the type
2563  */
2564  coldef->is_not_null = restdef->is_not_null;
2565  coldef->raw_default = restdef->raw_default;
2566  coldef->cooked_default = restdef->cooked_default;
2567  coldef->constraints = restdef->constraints;
2568  coldef->is_from_type = false;
2569  columns = list_delete_nth_cell(columns, restpos);
2570  }
2571  else
2572  ereport(ERROR,
2573  (errcode(ERRCODE_DUPLICATE_COLUMN),
2574  errmsg("column \"%s\" specified more than once",
2575  coldef->colname)));
2576  }
2577  else
2578  restpos++;
2579  }
2580  }
2581 
2582  /*
2583  * In case of a partition, there are no new column definitions, only dummy
2584  * ColumnDefs created for column constraints. Set them aside for now and
2585  * process them at the end.
2586  */
2587  if (is_partition)
2588  {
2589  saved_columns = columns;
2590  columns = NIL;
2591  }
2592 
2593  /*
2594  * Scan the parents left-to-right, and merge their attributes to form a
2595  * list of inherited columns (inh_columns).
2596  */
2597  child_attno = 0;
2598  foreach(lc, supers)
2599  {
2600  Oid parent = lfirst_oid(lc);
2601  Relation relation;
2602  TupleDesc tupleDesc;
2603  TupleConstr *constr;
2604  AttrMap *newattmap;
2605  List *inherited_defaults;
2606  List *cols_with_defaults;
2607  List *nnconstrs;
2608  ListCell *lc1;
2609  ListCell *lc2;
2610  Bitmapset *pkattrs;
2611  Bitmapset *nncols = NULL;
2612 
2613  /* caller already got lock */
2614  relation = table_open(parent, NoLock);
2615 
2616  /*
2617  * Check for active uses of the parent partitioned table in the
2618  * current transaction, such as being used in some manner by an
2619  * enclosing command.
2620  */
2621  if (is_partition)
2622  CheckTableNotInUse(relation, "CREATE TABLE .. PARTITION OF");
2623 
2624  /*
2625  * We do not allow partitioned tables and partitions to participate in
2626  * regular inheritance.
2627  */
2628  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && !is_partition)
2629  ereport(ERROR,
2630  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2631  errmsg("cannot inherit from partitioned table \"%s\"",
2632  RelationGetRelationName(relation))));
2633  if (relation->rd_rel->relispartition && !is_partition)
2634  ereport(ERROR,
2635  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2636  errmsg("cannot inherit from partition \"%s\"",
2637  RelationGetRelationName(relation))));
2638 
2639  if (relation->rd_rel->relkind != RELKIND_RELATION &&
2640  relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
2641  relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
2642  ereport(ERROR,
2643  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2644  errmsg("inherited relation \"%s\" is not a table or foreign table",
2645  RelationGetRelationName(relation))));
2646 
2647  /*
2648  * If the parent is permanent, so must be all of its partitions. Note
2649  * that inheritance allows that case.
2650  */
2651  if (is_partition &&
2652  relation->rd_rel->relpersistence != RELPERSISTENCE_TEMP &&
2653  relpersistence == RELPERSISTENCE_TEMP)
2654  ereport(ERROR,
2655  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2656  errmsg("cannot create a temporary relation as partition of permanent relation \"%s\"",
2657  RelationGetRelationName(relation))));
2658 
2659  /* Permanent rels cannot inherit from temporary ones */
2660  if (relpersistence != RELPERSISTENCE_TEMP &&
2661  relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
2662  ereport(ERROR,
2663  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2664  errmsg(!is_partition
2665  ? "cannot inherit from temporary relation \"%s\""
2666  : "cannot create a permanent relation as partition of temporary relation \"%s\"",
2667  RelationGetRelationName(relation))));
2668 
2669  /* If existing rel is temp, it must belong to this session */
2670  if (relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
2671  !relation->rd_islocaltemp)
2672  ereport(ERROR,
2673  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2674  errmsg(!is_partition
2675  ? "cannot inherit from temporary relation of another session"
2676  : "cannot create as partition of temporary relation of another session")));
2677 
2678  /*
2679  * We should have an UNDER permission flag for this, but for now,
2680  * demand that creator of a child table own the parent.
2681  */
2682  if (!object_ownercheck(RelationRelationId, RelationGetRelid(relation), GetUserId()))
2684  RelationGetRelationName(relation));
2685 
2686  tupleDesc = RelationGetDescr(relation);
2687  constr = tupleDesc->constr;
2688 
2689  /*
2690  * newattmap->attnums[] will contain the child-table attribute numbers
2691  * for the attributes of this parent table. (They are not the same
2692  * for parents after the first one, nor if we have dropped columns.)
2693  */
2694  newattmap = make_attrmap(tupleDesc->natts);
2695 
2696  /* We can't process inherited defaults until newattmap is complete. */
2697  inherited_defaults = cols_with_defaults = NIL;
2698 
2699  /*
2700  * All columns that are part of the parent's primary key need to be
2701  * NOT NULL; if partition just the attnotnull bit, otherwise a full
2702  * constraint (if they don't have one already). Also, we request
2703  * attnotnull on columns that have a not-null constraint that's not
2704  * marked NO INHERIT.
2705  */
2706  pkattrs = RelationGetIndexAttrBitmap(relation,
2708  nnconstrs = RelationGetNotNullConstraints(RelationGetRelid(relation), true);
2709  foreach(lc1, nnconstrs)
2710  nncols = bms_add_member(nncols,
2711  ((CookedConstraint *) lfirst(lc1))->attnum);
2712 
2713  for (AttrNumber parent_attno = 1; parent_attno <= tupleDesc->natts;
2714  parent_attno++)
2715  {
2716  Form_pg_attribute attribute = TupleDescAttr(tupleDesc,
2717  parent_attno - 1);
2718  char *attributeName = NameStr(attribute->attname);
2719  int exist_attno;
2720  ColumnDef *newdef;
2721  ColumnDef *mergeddef;
2722 
2723  /*
2724  * Ignore dropped columns in the parent.
2725  */
2726  if (attribute->attisdropped)
2727  continue; /* leave newattmap->attnums entry as zero */
2728 
2729  /*
2730  * Create new column definition
2731  */
2732  newdef = makeColumnDef(attributeName, attribute->atttypid,
2733  attribute->atttypmod, attribute->attcollation);
2734  newdef->storage = attribute->attstorage;
2735  newdef->generated = attribute->attgenerated;
2736  if (CompressionMethodIsValid(attribute->attcompression))
2737  newdef->compression =
2738  pstrdup(GetCompressionMethodName(attribute->attcompression));
2739 
2740  /*
2741  * Regular inheritance children are independent enough not to
2742  * inherit identity columns. But partitions are integral part of
2743  * a partitioned table and inherit identity column.
2744  */
2745  if (is_partition)
2746  newdef->identity = attribute->attidentity;
2747 
2748  /*
2749  * Does it match some previously considered column from another
2750  * parent?
2751  */
2752  exist_attno = findAttrByName(attributeName, inh_columns);
2753  if (exist_attno > 0)
2754  {
2755  /*
2756  * Yes, try to merge the two column definitions.
2757  */
2758  mergeddef = MergeInheritedAttribute(inh_columns, exist_attno, newdef);
2759 
2760  newattmap->attnums[parent_attno - 1] = exist_attno;
2761 
2762  /*
2763  * Partitions have only one parent, so conflict should never
2764  * occur.
2765  */
2766  Assert(!is_partition);
2767  }
2768  else
2769  {
2770  /*
2771  * No, create a new inherited column
2772  */
2773  newdef->inhcount = 1;
2774  newdef->is_local = false;
2775  inh_columns = lappend(inh_columns, newdef);
2776 
2777  newattmap->attnums[parent_attno - 1] = ++child_attno;
2778 
2779  mergeddef = newdef;
2780  }
2781 
2782  /*
2783  * mark attnotnull if parent has it and it's not NO INHERIT
2784  */
2785  if (bms_is_member(parent_attno, nncols) ||
2787  pkattrs))
2788  mergeddef->is_not_null = true;
2789 
2790  /*
2791  * In regular inheritance, columns in the parent's primary key get
2792  * an extra not-null constraint. Partitioning doesn't need this,
2793  * because the PK itself is going to be cloned to the partition.
2794  */
2795  if (!is_partition &&
2796  bms_is_member(parent_attno -
2798  pkattrs))
2799  {
2800  CookedConstraint *nn;
2801 
2802  nn = palloc(sizeof(CookedConstraint));
2803  nn->contype = CONSTR_NOTNULL;
2804  nn->conoid = InvalidOid;
2805  nn->name = NULL;
2806  nn->attnum = newattmap->attnums[parent_attno - 1];
2807  nn->expr = NULL;
2808  nn->skip_validation = false;
2809  nn->is_local = false;
2810  nn->inhcount = 1;
2811  nn->is_no_inherit = false;
2812 
2813  nnconstraints = lappend(nnconstraints, nn);
2814  }
2815 
2816  /*
2817  * Locate default/generation expression if any
2818  */
2819  if (attribute->atthasdef)
2820  {
2821  Node *this_default;
2822 
2823  this_default = TupleDescGetDefault(tupleDesc, parent_attno);
2824  if (this_default == NULL)
2825  elog(ERROR, "default expression not found for attribute %d of relation \"%s\"",
2826  parent_attno, RelationGetRelationName(relation));
2827 
2828  /*
2829  * If it's a GENERATED default, it might contain Vars that
2830  * need to be mapped to the inherited column(s)' new numbers.
2831  * We can't do that till newattmap is ready, so just remember
2832  * all the inherited default expressions for the moment.
2833  */
2834  inherited_defaults = lappend(inherited_defaults, this_default);
2835  cols_with_defaults = lappend(cols_with_defaults, mergeddef);
2836  }
2837  }
2838 
2839  /*
2840  * Now process any inherited default expressions, adjusting attnos
2841  * using the completed newattmap map.
2842  */
2843  forboth(lc1, inherited_defaults, lc2, cols_with_defaults)
2844  {
2845  Node *this_default = (Node *) lfirst(lc1);
2846  ColumnDef *def = (ColumnDef *) lfirst(lc2);
2847  bool found_whole_row;
2848 
2849  /* Adjust Vars to match new table's column numbering */
2850  this_default = map_variable_attnos(this_default,
2851  1, 0,
2852  newattmap,
2853  InvalidOid, &found_whole_row);
2854 
2855  /*
2856  * For the moment we have to reject whole-row variables. We could
2857  * convert them, if we knew the new table's rowtype OID, but that
2858  * hasn't been assigned yet. (A variable could only appear in a
2859  * generation expression, so the error message is correct.)
2860  */
2861  if (found_whole_row)
2862  ereport(ERROR,
2863  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2864  errmsg("cannot convert whole-row table reference"),
2865  errdetail("Generation expression for column \"%s\" contains a whole-row reference to table \"%s\".",
2866  def->colname,
2867  RelationGetRelationName(relation))));
2868 
2869  /*
2870  * If we already had a default from some prior parent, check to
2871  * see if they are the same. If so, no problem; if not, mark the
2872  * column as having a bogus default. Below, we will complain if
2873  * the bogus default isn't overridden by the child columns.
2874  */
2875  Assert(def->raw_default == NULL);
2876  if (def->cooked_default == NULL)
2877  def->cooked_default = this_default;
2878  else if (!equal(def->cooked_default, this_default))
2879  {
2880  def->cooked_default = &bogus_marker;
2881  have_bogus_defaults = true;
2882  }
2883  }
2884 
2885  /*
2886  * Now copy the CHECK constraints of this parent, adjusting attnos
2887  * using the completed newattmap map. Identically named constraints
2888  * are merged if possible, else we throw error.
2889  */
2890  if (constr && constr->num_check > 0)
2891  {
2892  ConstrCheck *check = constr->check;
2893 
2894  for (int i = 0; i < constr->num_check; i++)
2895  {
2896  char *name = check[i].ccname;
2897  Node *expr;
2898  bool found_whole_row;
2899 
2900  /* ignore if the constraint is non-inheritable */
2901  if (check[i].ccnoinherit)
2902  continue;
2903 
2904  /* Adjust Vars to match new table's column numbering */
2905  expr = map_variable_attnos(stringToNode(check[i].ccbin),
2906  1, 0,
2907  newattmap,
2908  InvalidOid, &found_whole_row);
2909 
2910  /*
2911  * For the moment we have to reject whole-row variables. We
2912  * could convert them, if we knew the new table's rowtype OID,
2913  * but that hasn't been assigned yet.
2914  */
2915  if (found_whole_row)
2916  ereport(ERROR,
2917  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2918  errmsg("cannot convert whole-row table reference"),
2919  errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
2920  name,
2921  RelationGetRelationName(relation))));
2922 
2923  constraints = MergeCheckConstraint(constraints, name, expr);
2924  }
2925  }
2926 
2927  /*
2928  * Also copy the not-null constraints from this parent. The
2929  * attnotnull markings were already installed above.
2930  */
2931  foreach(lc1, nnconstrs)
2932  {
2933  CookedConstraint *nn = lfirst(lc1);
2934 
2935  Assert(nn->contype == CONSTR_NOTNULL);
2936 
2937  nn->attnum = newattmap->attnums[nn->attnum - 1];
2938  nn->is_local = false;
2939  nn->inhcount = 1;
2940 
2941  nnconstraints = lappend(nnconstraints, nn);
2942  }
2943 
2944  free_attrmap(newattmap);
2945 
2946  /*
2947  * Close the parent rel, but keep our lock on it until xact commit.
2948  * That will prevent someone else from deleting or ALTERing the parent
2949  * before the child is committed.
2950  */
2951  table_close(relation, NoLock);
2952  }
2953 
2954  /*
2955  * If we had no inherited attributes, the result columns are just the
2956  * explicitly declared columns. Otherwise, we need to merge the declared
2957  * columns into the inherited column list. Although, we never have any
2958  * explicitly declared columns if the table is a partition.
2959  */
2960  if (inh_columns != NIL)
2961  {
2962  int newcol_attno = 0;
2963 
2964  foreach(lc, columns)
2965  {
2966  ColumnDef *newdef = lfirst_node(ColumnDef, lc);
2967  char *attributeName = newdef->colname;
2968  int exist_attno;
2969 
2970  /*
2971  * Partitions have only one parent and have no column definitions
2972  * of their own, so conflict should never occur.
2973  */
2974  Assert(!is_partition);
2975 
2976  newcol_attno++;
2977 
2978  /*
2979  * Does it match some inherited column?
2980  */
2981  exist_attno = findAttrByName(attributeName, inh_columns);
2982  if (exist_attno > 0)
2983  {
2984  /*
2985  * Yes, try to merge the two column definitions.
2986  */
2987  MergeChildAttribute(inh_columns, exist_attno, newcol_attno, newdef);
2988  }
2989  else
2990  {
2991  /*
2992  * No, attach new column unchanged to result columns.
2993  */
2994  inh_columns = lappend(inh_columns, newdef);
2995  }
2996  }
2997 
2998  columns = inh_columns;
2999 
3000  /*
3001  * Check that we haven't exceeded the legal # of columns after merging
3002  * in inherited columns.
3003  */
3004  if (list_length(columns) > MaxHeapAttributeNumber)
3005  ereport(ERROR,
3006  (errcode(ERRCODE_TOO_MANY_COLUMNS),
3007  errmsg("tables can have at most %d columns",
3009  }
3010 
3011  /*
3012  * Now that we have the column definition list for a partition, we can
3013  * check whether the columns referenced in the column constraint specs
3014  * actually exist. Also, merge column defaults.
3015  */
3016  if (is_partition)
3017  {
3018  foreach(lc, saved_columns)
3019  {
3020  ColumnDef *restdef = lfirst(lc);
3021  bool found = false;
3022  ListCell *l;
3023 
3024  foreach(l, columns)
3025  {
3026  ColumnDef *coldef = lfirst(l);
3027 
3028  if (strcmp(coldef->colname, restdef->colname) == 0)
3029  {
3030  found = true;
3031 
3032  /*
3033  * Check for conflicts related to generated columns.
3034  *
3035  * Same rules as above: generated-ness has to match the
3036  * parent, but the contents of the generation expression
3037  * can be different.
3038  */
3039  if (coldef->generated)
3040  {
3041  if (restdef->raw_default && !restdef->generated)
3042  ereport(ERROR,
3043  (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3044  errmsg("column \"%s\" inherits from generated column but specifies default",
3045  restdef->colname)));
3046  if (restdef->identity)
3047  ereport(ERROR,
3048  (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3049  errmsg("column \"%s\" inherits from generated column but specifies identity",
3050  restdef->colname)));
3051  }
3052  else
3053  {
3054  if (restdef->generated)
3055  ereport(ERROR,
3056  (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3057  errmsg("child column \"%s\" specifies generation expression",
3058  restdef->colname),
3059  errhint("A child table column cannot be generated unless its parent column is.")));
3060  }
3061 
3062  /*
3063  * Override the parent's default value for this column
3064  * (coldef->cooked_default) with the partition's local
3065  * definition (restdef->raw_default), if there's one. It
3066  * should be physically impossible to get a cooked default
3067  * in the local definition or a raw default in the
3068  * inherited definition, but make sure they're nulls, for
3069  * future-proofing.
3070  */
3071  Assert(restdef->cooked_default == NULL);
3072  Assert(coldef->raw_default == NULL);
3073  if (restdef->raw_default)
3074  {
3075  coldef->raw_default = restdef->raw_default;
3076  coldef->cooked_default = NULL;
3077  }
3078  }
3079  }
3080 
3081  /* complain for constraints on columns not in parent */
3082  if (!found)
3083  ereport(ERROR,
3084  (errcode(ERRCODE_UNDEFINED_COLUMN),
3085  errmsg("column \"%s\" does not exist",
3086  restdef->colname)));
3087  }
3088  }
3089 
3090  /*
3091  * If we found any conflicting parent default values, check to make sure
3092  * they were overridden by the child.
3093  */
3094  if (have_bogus_defaults)
3095  {
3096  foreach(lc, columns)
3097  {
3098  ColumnDef *def = lfirst(lc);
3099 
3100  if (def->cooked_default == &bogus_marker)
3101  {
3102  if (def->generated)
3103  ereport(ERROR,
3104  (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3105  errmsg("column \"%s\" inherits conflicting generation expressions",
3106  def->colname),
3107  errhint("To resolve the conflict, specify a generation expression explicitly.")));
3108  else
3109  ereport(ERROR,
3110  (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3111  errmsg("column \"%s\" inherits conflicting default values",
3112  def->colname),
3113  errhint("To resolve the conflict, specify a default explicitly.")));
3114  }
3115  }
3116  }
3117 
3118  *supconstr = constraints;
3119  *supnotnulls = nnconstraints;
3120 
3121  return columns;
3122 }
3123 
3124 
3125 /*
3126  * MergeCheckConstraint
3127  * Try to merge an inherited CHECK constraint with previous ones
3128  *
3129  * If we inherit identically-named constraints from multiple parents, we must
3130  * merge them, or throw an error if they don't have identical definitions.
3131  *
3132  * constraints is a list of CookedConstraint structs for previous constraints.
3133  *
3134  * If the new constraint matches an existing one, then the existing
3135  * constraint's inheritance count is updated. If there is a conflict (same
3136  * name but different expression), throw an error. If the constraint neither
3137  * matches nor conflicts with an existing one, a new constraint is appended to
3138  * the list.
3139  */
3140 static List *
3141 MergeCheckConstraint(List *constraints, const char *name, Node *expr)
3142 {
3143  ListCell *lc;
3144  CookedConstraint *newcon;
3145 
3146  foreach(lc, constraints)
3147  {
3148  CookedConstraint *ccon = (CookedConstraint *) lfirst(lc);
3149 
3150  Assert(ccon->contype == CONSTR_CHECK);
3151 
3152  /* Non-matching names never conflict */
3153  if (strcmp(ccon->name, name) != 0)
3154  continue;
3155 
3156  if (equal(expr, ccon->expr))
3157  {
3158  /* OK to merge constraint with existing */
3159  ccon->inhcount++;
3160  if (ccon->inhcount < 0)
3161  ereport(ERROR,
3162  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3163  errmsg("too many inheritance parents"));
3164  return constraints;
3165  }
3166 
3167  ereport(ERROR,
3169  errmsg("check constraint name \"%s\" appears multiple times but with different expressions",
3170  name)));
3171  }
3172 
3173  /*
3174  * Constraint couldn't be merged with an existing one and also didn't
3175  * conflict with an existing one, so add it as a new one to the list.
3176  */
3177  newcon = palloc0_object(CookedConstraint);
3178  newcon->contype = CONSTR_CHECK;
3179  newcon->name = pstrdup(name);
3180  newcon->expr = expr;
3181  newcon->inhcount = 1;
3182  return lappend(constraints, newcon);
3183 }
3184 
3185 /*
3186  * MergeChildAttribute
3187  * Merge given child attribute definition into given inherited attribute.
3188  *
3189  * Input arguments:
3190  * 'inh_columns' is the list of inherited ColumnDefs.
3191  * 'exist_attno' is the number of the inherited attribute in inh_columns
3192  * 'newcol_attno' is the attribute number in child table's schema definition
3193  * 'newdef' is the column/attribute definition from the child table.
3194  *
3195  * The ColumnDef in 'inh_columns' list is modified. The child attribute's
3196  * ColumnDef remains unchanged.
3197  *
3198  * Notes:
3199  * - The attribute is merged according to the rules laid out in the prologue
3200  * of MergeAttributes().
3201  * - If matching inherited attribute exists but the child attribute can not be
3202  * merged into it, the function throws respective errors.
3203  * - A partition can not have its own column definitions. Hence this function
3204  * is applicable only to a regular inheritance child.
3205  */
3206 static void
3207 MergeChildAttribute(List *inh_columns, int exist_attno, int newcol_attno, const ColumnDef *newdef)
3208 {
3209  char *attributeName = newdef->colname;
3210  ColumnDef *inhdef;
3211  Oid inhtypeid,
3212  newtypeid;
3213  int32 inhtypmod,
3214  newtypmod;
3215  Oid inhcollid,
3216  newcollid;
3217 
3218  if (exist_attno == newcol_attno)
3219  ereport(NOTICE,
3220  (errmsg("merging column \"%s\" with inherited definition",
3221  attributeName)));
3222  else
3223  ereport(NOTICE,
3224  (errmsg("moving and merging column \"%s\" with inherited definition", attributeName),
3225  errdetail("User-specified column moved to the position of the inherited column.")));
3226 
3227  inhdef = list_nth_node(ColumnDef, inh_columns, exist_attno - 1);
3228 
3229  /*
3230  * Must have the same type and typmod
3231  */
3232  typenameTypeIdAndMod(NULL, inhdef->typeName, &inhtypeid, &inhtypmod);
3233  typenameTypeIdAndMod(NULL, newdef->typeName, &newtypeid, &newtypmod);
3234  if (inhtypeid != newtypeid || inhtypmod != newtypmod)
3235  ereport(ERROR,
3236  (errcode(ERRCODE_DATATYPE_MISMATCH),
3237  errmsg("column \"%s\" has a type conflict",
3238  attributeName),
3239  errdetail("%s versus %s",
3240  format_type_with_typemod(inhtypeid, inhtypmod),
3241  format_type_with_typemod(newtypeid, newtypmod))));
3242 
3243  /*
3244  * Must have the same collation
3245  */
3246  inhcollid = GetColumnDefCollation(NULL, inhdef, inhtypeid);
3247  newcollid = GetColumnDefCollation(NULL, newdef, newtypeid);
3248  if (inhcollid != newcollid)
3249  ereport(ERROR,
3250  (errcode(ERRCODE_COLLATION_MISMATCH),
3251  errmsg("column \"%s\" has a collation conflict",
3252  attributeName),
3253  errdetail("\"%s\" versus \"%s\"",
3254  get_collation_name(inhcollid),
3255  get_collation_name(newcollid))));
3256 
3257  /*
3258  * Identity is never inherited by a regular inheritance child. Pick
3259  * child's identity definition if there's one.
3260  */
3261  inhdef->identity = newdef->identity;
3262 
3263  /*
3264  * Copy storage parameter
3265  */
3266  if (inhdef->storage == 0)
3267  inhdef->storage = newdef->storage;
3268  else if (newdef->storage != 0 && inhdef->storage != newdef->storage)
3269  ereport(ERROR,
3270  (errcode(ERRCODE_DATATYPE_MISMATCH),
3271  errmsg("column \"%s\" has a storage parameter conflict",
3272  attributeName),
3273  errdetail("%s versus %s",
3274  storage_name(inhdef->storage),
3275  storage_name(newdef->storage))));
3276 
3277  /*
3278  * Copy compression parameter
3279  */
3280  if (inhdef->compression == NULL)
3281  inhdef->compression = newdef->compression;
3282  else if (newdef->compression != NULL)
3283  {
3284  if (strcmp(inhdef->compression, newdef->compression) != 0)
3285  ereport(ERROR,
3286  (errcode(ERRCODE_DATATYPE_MISMATCH),
3287  errmsg("column \"%s\" has a compression method conflict",
3288  attributeName),
3289  errdetail("%s versus %s", inhdef->compression, newdef->compression)));
3290  }
3291 
3292  /*
3293  * Merge of not-null constraints = OR 'em together
3294  */
3295  inhdef->is_not_null |= newdef->is_not_null;
3296 
3297  /*
3298  * Check for conflicts related to generated columns.
3299  *
3300  * If the parent column is generated, the child column will be made a
3301  * generated column if it isn't already. If it is a generated column,
3302  * we'll take its generation expression in preference to the parent's. We
3303  * must check that the child column doesn't specify a default value or
3304  * identity, which matches the rules for a single column in
3305  * parse_utilcmd.c.
3306  *
3307  * Conversely, if the parent column is not generated, the child column
3308  * can't be either. (We used to allow that, but it results in being able
3309  * to override the generation expression via UPDATEs through the parent.)
3310  */
3311  if (inhdef->generated)
3312  {
3313  if (newdef->raw_default && !newdef->generated)
3314  ereport(ERROR,
3315  (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3316  errmsg("column \"%s\" inherits from generated column but specifies default",
3317  inhdef->colname)));
3318  if (newdef->identity)
3319  ereport(ERROR,
3320  (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3321  errmsg("column \"%s\" inherits from generated column but specifies identity",
3322  inhdef->colname)));
3323  }
3324  else
3325  {
3326  if (newdef->generated)
3327  ereport(ERROR,
3328  (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
3329  errmsg("child column \"%s\" specifies generation expression",
3330  inhdef->colname),
3331  errhint("A child table column cannot be generated unless its parent column is.")));
3332  }
3333 
3334  /*
3335  * If new def has a default, override previous default
3336  */
3337  if (newdef->raw_default != NULL)
3338  {
3339  inhdef->raw_default = newdef->raw_default;
3340  inhdef->cooked_default = newdef->cooked_default;
3341  }
3342 
3343  /* Mark the column as locally defined */
3344  inhdef->is_local = true;
3345 }
3346 
3347 /*
3348  * MergeInheritedAttribute
3349  * Merge given parent attribute definition into specified attribute
3350  * inherited from the previous parents.
3351  *
3352  * Input arguments:
3353  * 'inh_columns' is the list of previously inherited ColumnDefs.
3354  * 'exist_attno' is the number the existing matching attribute in inh_columns.
3355  * 'newdef' is the new parent column/attribute definition to be merged.
3356  *
3357  * The matching ColumnDef in 'inh_columns' list is modified and returned.
3358  *
3359  * Notes:
3360  * - The attribute is merged according to the rules laid out in the prologue
3361  * of MergeAttributes().
3362  * - If matching inherited attribute exists but the new attribute can not be
3363  * merged into it, the function throws respective errors.
3364  * - A partition inherits from only a single parent. Hence this function is
3365  * applicable only to a regular inheritance.
3366  */
3367 static ColumnDef *
3369  int exist_attno,
3370  const ColumnDef *newdef)
3371 {
3372  char *attributeName = newdef->colname;
3373  ColumnDef *prevdef;
3374  Oid prevtypeid,
3375  newtypeid;
3376  int32 prevtypmod,
3377  newtypmod;
3378  Oid prevcollid,
3379  newcollid;
3380 
3381  ereport(NOTICE,
3382  (errmsg("merging multiple inherited definitions of column \"%s\"",
3383  attributeName)));
3384  prevdef = list_nth_node(ColumnDef, inh_columns, exist_attno - 1);
3385 
3386  /*
3387  * Must have the same type and typmod
3388  */
3389  typenameTypeIdAndMod(NULL, prevdef->typeName, &prevtypeid, &prevtypmod);
3390  typenameTypeIdAndMod(NULL, newdef->typeName, &newtypeid, &newtypmod);
3391  if (prevtypeid != newtypeid || prevtypmod != newtypmod)
3392  ereport(ERROR,
3393  (errcode(ERRCODE_DATATYPE_MISMATCH),
3394  errmsg("inherited column \"%s\" has a type conflict",
3395  attributeName),
3396  errdetail("%s versus %s",
3397  format_type_with_typemod(prevtypeid, prevtypmod),
3398  format_type_with_typemod(newtypeid, newtypmod))));
3399 
3400  /*
3401  * Must have the same collation
3402  */
3403  prevcollid = GetColumnDefCollation(NULL, prevdef, prevtypeid);
3404  newcollid = GetColumnDefCollation(NULL, newdef, newtypeid);
3405  if (prevcollid != newcollid)
3406  ereport(ERROR,
3407  (errcode(ERRCODE_COLLATION_MISMATCH),
3408  errmsg("inherited column \"%s\" has a collation conflict",
3409  attributeName),
3410  errdetail("\"%s\" versus \"%s\"",
3411  get_collation_name(prevcollid),
3412  get_collation_name(newcollid))));
3413 
3414  /*
3415  * Copy/check storage parameter
3416  */
3417  if (prevdef->storage == 0)
3418  prevdef->storage = newdef->storage;
3419  else if (prevdef->storage != newdef->storage)
3420  ereport(ERROR,
3421  (errcode(ERRCODE_DATATYPE_MISMATCH),
3422  errmsg("inherited column \"%s\" has a storage parameter conflict",
3423  attributeName),
3424  errdetail("%s versus %s",
3425  storage_name(prevdef->storage),
3426  storage_name(newdef->storage))));
3427 
3428  /*
3429  * Copy/check compression parameter
3430  */
3431  if (prevdef->compression == NULL)
3432  prevdef->compression = newdef->compression;
3433  else if (strcmp(prevdef->compression, newdef->compression) != 0)
3434  ereport(ERROR,
3435  (errcode(ERRCODE_DATATYPE_MISMATCH),
3436  errmsg("column \"%s\" has a compression method conflict",
3437  attributeName),
3438  errdetail("%s versus %s", prevdef->compression, newdef->compression)));
3439 
3440  /*
3441  * Check for GENERATED conflicts
3442  */
3443  if (prevdef->generated != newdef->generated)
3444  ereport(ERROR,
3445  (errcode(ERRCODE_DATATYPE_MISMATCH),
3446  errmsg("inherited column \"%s\" has a generation conflict",
3447  attributeName)));
3448 
3449  /*
3450  * Default and other constraints are handled by the caller.
3451  */
3452 
3453  prevdef->inhcount++;
3454  if (prevdef->inhcount < 0)
3455  ereport(ERROR,
3456  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3457  errmsg("too many inheritance parents"));
3458 
3459  return prevdef;
3460 }
3461 
3462 /*
3463  * StoreCatalogInheritance
3464  * Updates the system catalogs with proper inheritance information.
3465  *
3466  * supers is a list of the OIDs of the new relation's direct ancestors.
3467  */
3468 static void
3469 StoreCatalogInheritance(Oid relationId, List *supers,
3470  bool child_is_partition)
3471 {
3472  Relation relation;
3473  int32 seqNumber;
3474  ListCell *entry;
3475 
3476  /*
3477  * sanity checks
3478  */
3479  Assert(OidIsValid(relationId));
3480 
3481  if (supers == NIL)
3482  return;
3483 
3484  /*
3485  * Store INHERITS information in pg_inherits using direct ancestors only.
3486  * Also enter dependencies on the direct ancestors, and make sure they are
3487  * marked with relhassubclass = true.
3488  *
3489  * (Once upon a time, both direct and indirect ancestors were found here
3490  * and then entered into pg_ipl. Since that catalog doesn't exist
3491  * anymore, there's no need to look for indirect ancestors.)
3492  */
3493  relation = table_open(InheritsRelationId, RowExclusiveLock);
3494 
3495  seqNumber = 1;
3496  foreach(entry, supers)
3497  {
3498  Oid parentOid = lfirst_oid(entry);
3499 
3500  StoreCatalogInheritance1(relationId, parentOid, seqNumber, relation,
3501  child_is_partition);
3502  seqNumber++;
3503  }
3504 
3505  table_close(relation, RowExclusiveLock);
3506 }
3507 
3508 /*
3509  * Make catalog entries showing relationId as being an inheritance child
3510  * of parentOid. inhRelation is the already-opened pg_inherits catalog.
3511  */
3512 static void
3513 StoreCatalogInheritance1(Oid relationId, Oid parentOid,
3514  int32 seqNumber, Relation inhRelation,
3515  bool child_is_partition)
3516 {
3517  ObjectAddress childobject,
3518  parentobject;
3519 
3520  /* store the pg_inherits row */
3521  StoreSingleInheritance(relationId, parentOid, seqNumber);
3522 
3523  /*
3524  * Store a dependency too
3525  */
3526  parentobject.classId = RelationRelationId;
3527  parentobject.objectId = parentOid;
3528  parentobject.objectSubId = 0;
3529  childobject.classId = RelationRelationId;
3530  childobject.objectId = relationId;
3531  childobject.objectSubId = 0;
3532 
3533  recordDependencyOn(&childobject, &parentobject,
3534  child_dependency_type(child_is_partition));
3535 
3536  /*
3537  * Post creation hook of this inheritance. Since object_access_hook
3538  * doesn't take multiple object identifiers, we relay oid of parent
3539  * relation using auxiliary_id argument.
3540  */
3541  InvokeObjectPostAlterHookArg(InheritsRelationId,
3542  relationId, 0,
3543  parentOid, false);
3544 
3545  /*
3546  * Mark the parent as having subclasses.
3547  */
3548  SetRelationHasSubclass(parentOid, true);
3549 }
3550 
3551 /*
3552  * Look for an existing column entry with the given name.
3553  *
3554  * Returns the index (starting with 1) if attribute already exists in columns,
3555  * 0 if it doesn't.
3556  */
3557 static int
3558 findAttrByName(const char *attributeName, const List *columns)
3559 {
3560  ListCell *lc;
3561  int i = 1;
3562 
3563  foreach(lc, columns)
3564  {
3565  if (strcmp(attributeName, lfirst_node(ColumnDef, lc)->colname) == 0)
3566  return i;
3567 
3568  i++;
3569  }
3570  return 0;
3571 }
3572 
3573 
3574 /*
3575  * SetRelationHasSubclass
3576  * Set the value of the relation's relhassubclass field in pg_class.
3577  *
3578  * NOTE: caller must be holding an appropriate lock on the relation.
3579  * ShareUpdateExclusiveLock is sufficient.
3580  *
3581  * NOTE: an important side-effect of this operation is that an SI invalidation
3582  * message is sent out to all backends --- including me --- causing plans
3583  * referencing the relation to be rebuilt with the new list of children.
3584  * This must happen even if we find that no change is needed in the pg_class
3585  * row.
3586  */
3587 void
3588 SetRelationHasSubclass(Oid relationId, bool relhassubclass)
3589 {
3590  Relation relationRelation;
3591  HeapTuple tuple;
3592  Form_pg_class classtuple;
3593 
3594  /*
3595  * Fetch a modifiable copy of the tuple, modify it, update pg_class.
3596  */
3597  relationRelation = table_open(RelationRelationId, RowExclusiveLock);
3598  tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
3599  if (!HeapTupleIsValid(tuple))
3600  elog(ERROR, "cache lookup failed for relation %u", relationId);
3601  classtuple = (Form_pg_class) GETSTRUCT(tuple);
3602 
3603  if (classtuple->relhassubclass != relhassubclass)
3604  {
3605  classtuple->relhassubclass = relhassubclass;
3606  CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
3607  }
3608  else
3609  {
3610  /* no need to change tuple, but force relcache rebuild anyway */
3612  }
3613 
3614  heap_freetuple(tuple);
3615  table_close(relationRelation, RowExclusiveLock);
3616 }
3617 
3618 /*
3619  * CheckRelationTableSpaceMove
3620  * Check if relation can be moved to new tablespace.
3621  *
3622  * NOTE: The caller must hold AccessExclusiveLock on the relation.
3623  *
3624  * Returns true if the relation can be moved to the new tablespace; raises
3625  * an error if it is not possible to do the move; returns false if the move
3626  * would have no effect.
3627  */
3628 bool
3630 {
3631  Oid oldTableSpaceId;
3632 
3633  /*
3634  * No work if no change in tablespace. Note that MyDatabaseTableSpace is
3635  * stored as 0.
3636  */
3637  oldTableSpaceId = rel->rd_rel->reltablespace;
3638  if (newTableSpaceId == oldTableSpaceId ||
3639  (newTableSpaceId == MyDatabaseTableSpace && oldTableSpaceId == 0))
3640  return false;
3641 
3642  /*
3643  * We cannot support moving mapped relations into different tablespaces.
3644  * (In particular this eliminates all shared catalogs.)
3645  */
3646  if (RelationIsMapped(rel))
3647  ereport(ERROR,
3648  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3649  errmsg("cannot move system relation \"%s\"",
3650  RelationGetRelationName(rel))));
3651 
3652  /* Cannot move a non-shared relation into pg_global */
3653  if (newTableSpaceId == GLOBALTABLESPACE_OID)
3654  ereport(ERROR,
3655  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3656  errmsg("only shared relations can be placed in pg_global tablespace")));
3657 
3658  /*
3659  * Do not allow moving temp tables of other backends ... their local
3660  * buffer manager is not going to cope.
3661  */
3662  if (RELATION_IS_OTHER_TEMP(rel))
3663  ereport(ERROR,
3664  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3665  errmsg("cannot move temporary tables of other sessions")));
3666 
3667  return true;
3668 }
3669 
3670 /*
3671  * SetRelationTableSpace
3672  * Set new reltablespace and relfilenumber in pg_class entry.
3673  *
3674  * newTableSpaceId is the new tablespace for the relation, and
3675  * newRelFilenumber its new filenumber. If newRelFilenumber is
3676  * InvalidRelFileNumber, this field is not updated.
3677  *
3678  * NOTE: The caller must hold AccessExclusiveLock on the relation.
3679  *
3680  * The caller of this routine had better check if a relation can be
3681  * moved to this new tablespace by calling CheckRelationTableSpaceMove()
3682  * first, and is responsible for making the change visible with
3683  * CommandCounterIncrement().
3684  */
3685 void
3687  Oid newTableSpaceId,
3688  RelFileNumber newRelFilenumber)
3689 {
3690  Relation pg_class;
3691  HeapTuple tuple;
3692  Form_pg_class rd_rel;
3693  Oid reloid = RelationGetRelid(rel);
3694 
3695  Assert(CheckRelationTableSpaceMove(rel, newTableSpaceId));
3696 
3697  /* Get a modifiable copy of the relation's pg_class row. */
3698  pg_class = table_open(RelationRelationId, RowExclusiveLock);
3699 
3700  tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(reloid));
3701  if (!HeapTupleIsValid(tuple))
3702  elog(ERROR, "cache lookup failed for relation %u", reloid);
3703  rd_rel = (Form_pg_class) GETSTRUCT(tuple);
3704 
3705  /* Update the pg_class row. */
3706  rd_rel->reltablespace = (newTableSpaceId == MyDatabaseTableSpace) ?
3707  InvalidOid : newTableSpaceId;
3708  if (RelFileNumberIsValid(newRelFilenumber))
3709  rd_rel->relfilenode = newRelFilenumber;
3710  CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3711 
3712  /*
3713  * Record dependency on tablespace. This is only required for relations
3714  * that have no physical storage.
3715  */
3716  if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
3717  changeDependencyOnTablespace(RelationRelationId, reloid,
3718  rd_rel->reltablespace);
3719 
3720  heap_freetuple(tuple);
3721  table_close(pg_class, RowExclusiveLock);
3722 }
3723 
3724 /*
3725  * renameatt_check - basic sanity checks before attribute rename
3726  */
3727 static void
3728 renameatt_check(Oid myrelid, Form_pg_class classform, bool recursing)
3729 {
3730  char relkind = classform->relkind;
3731 
3732  if (classform->reloftype && !recursing)
3733  ereport(ERROR,
3734  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3735  errmsg("cannot rename column of typed table")));
3736 
3737  /*
3738  * Renaming the columns of sequences or toast tables doesn't actually
3739  * break anything from the system's point of view, since internal
3740  * references are by attnum. But it doesn't seem right to allow users to
3741  * change names that are hardcoded into the system, hence the following
3742  * restriction.
3743  */
3744  if (relkind != RELKIND_RELATION &&
3745  relkind != RELKIND_VIEW &&
3746  relkind != RELKIND_MATVIEW &&
3747  relkind != RELKIND_COMPOSITE_TYPE &&
3748  relkind != RELKIND_INDEX &&
3749  relkind != RELKIND_PARTITIONED_INDEX &&
3750  relkind != RELKIND_FOREIGN_TABLE &&
3751  relkind != RELKIND_PARTITIONED_TABLE)
3752  ereport(ERROR,
3753  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3754  errmsg("cannot rename columns of relation \"%s\"",
3755  NameStr(classform->relname)),
3757 
3758  /*
3759  * permissions checking. only the owner of a class can change its schema.
3760  */
3761  if (!object_ownercheck(RelationRelationId, myrelid, GetUserId()))
3763  NameStr(classform->relname));
3764  if (!allowSystemTableMods && IsSystemClass(myrelid, classform))
3765  ereport(ERROR,
3766  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3767  errmsg("permission denied: \"%s\" is a system catalog",
3768  NameStr(classform->relname))));
3769 }
3770 
3771 /*
3772  * renameatt_internal - workhorse for renameatt
3773  *
3774  * Return value is the attribute number in the 'myrelid' relation.
3775  */
3776 static AttrNumber
3778  const char *oldattname,
3779  const char *newattname,
3780  bool recurse,
3781  bool recursing,
3782  int expected_parents,
3783  DropBehavior behavior)
3784 {
3785  Relation targetrelation;
3786  Relation attrelation;
3787  HeapTuple atttup;
3788  Form_pg_attribute attform;
3790 
3791  /*
3792  * Grab an exclusive lock on the target table, which we will NOT release
3793  * until end of transaction.
3794  */
3795  targetrelation = relation_open(myrelid, AccessExclusiveLock);
3796  renameatt_check(myrelid, RelationGetForm(targetrelation), recursing);
3797 
3798  /*
3799  * if the 'recurse' flag is set then we are supposed to rename this
3800  * attribute in all classes that inherit from 'relname' (as well as in
3801  * 'relname').
3802  *
3803  * any permissions or problems with duplicate attributes will cause the
3804  * whole transaction to abort, which is what we want -- all or nothing.
3805  */
3806  if (recurse)
3807  {
3808  List *child_oids,
3809  *child_numparents;
3810  ListCell *lo,
3811  *li;
3812 
3813  /*
3814  * we need the number of parents for each child so that the recursive
3815  * calls to renameatt() can determine whether there are any parents
3816  * outside the inheritance hierarchy being processed.
3817  */
3818  child_oids = find_all_inheritors(myrelid, AccessExclusiveLock,
3819  &child_numparents);
3820 
3821  /*
3822  * find_all_inheritors does the recursive search of the inheritance
3823  * hierarchy, so all we have to do is process all of the relids in the
3824  * list that it returns.
3825  */
3826  forboth(lo, child_oids, li, child_numparents)
3827  {
3828  Oid childrelid = lfirst_oid(lo);
3829  int numparents = lfirst_int(li);
3830 
3831  if (childrelid == myrelid)
3832  continue;
3833  /* note we need not recurse again */
3834  renameatt_internal(childrelid, oldattname, newattname, false, true, numparents, behavior);
3835  }
3836  }
3837  else
3838  {
3839  /*
3840  * If we are told not to recurse, there had better not be any child
3841  * tables; else the rename would put them out of step.
3842  *
3843  * expected_parents will only be 0 if we are not already recursing.
3844  */
3845  if (expected_parents == 0 &&
3846  find_inheritance_children(myrelid, NoLock) != NIL)
3847  ereport(ERROR,
3848  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3849  errmsg("inherited column \"%s\" must be renamed in child tables too",
3850  oldattname)));
3851  }
3852 
3853  /* rename attributes in typed tables of composite type */
3854  if (targetrelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
3855  {
3856  List *child_oids;
3857  ListCell *lo;
3858 
3859  child_oids = find_typed_table_dependencies(targetrelation->rd_rel->reltype,
3860  RelationGetRelationName(targetrelation),
3861  behavior);
3862 
3863  foreach(lo, child_oids)
3864  renameatt_internal(lfirst_oid(lo), oldattname, newattname, true, true, 0, behavior);
3865  }
3866 
3867  attrelation = table_open(AttributeRelationId, RowExclusiveLock);
3868 
3869  atttup = SearchSysCacheCopyAttName(myrelid, oldattname);
3870  if (!HeapTupleIsValid(atttup))
3871  ereport(ERROR,
3872  (errcode(ERRCODE_UNDEFINED_COLUMN),
3873  errmsg("column \"%s\" does not exist",
3874  oldattname)));
3875  attform = (Form_pg_attribute) GETSTRUCT(atttup);
3876 
3877  attnum = attform->attnum;
3878  if (attnum <= 0)
3879  ereport(ERROR,
3880  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3881  errmsg("cannot rename system column \"%s\"",
3882  oldattname)));
3883 
3884  /*
3885  * if the attribute is inherited, forbid the renaming. if this is a
3886  * top-level call to renameatt(), then expected_parents will be 0, so the
3887  * effect of this code will be to prohibit the renaming if the attribute
3888  * is inherited at all. if this is a recursive call to renameatt(),
3889  * expected_parents will be the number of parents the current relation has
3890  * within the inheritance hierarchy being processed, so we'll prohibit the
3891  * renaming only if there are additional parents from elsewhere.
3892  */
3893  if (attform->attinhcount > expected_parents)
3894  ereport(ERROR,
3895  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
3896  errmsg("cannot rename inherited column \"%s\"",
3897  oldattname)));
3898 
3899  /* new name should not already exist */
3900  (void) check_for_column_name_collision(targetrelation, newattname, false);
3901 
3902  /* apply the update */
3903  namestrcpy(&(attform->attname), newattname);
3904 
3905  CatalogTupleUpdate(attrelation, &atttup->t_self, atttup);
3906 
3907  InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum);
3908 
3909  heap_freetuple(atttup);
3910 
3911  table_close(attrelation, RowExclusiveLock);
3912 
3913  relation_close(targetrelation, NoLock); /* close rel but keep lock */
3914 
3915  return attnum;
3916 }
3917 
3918 /*
3919  * Perform permissions and integrity checks before acquiring a relation lock.
3920  */
3921 static void
3923  void *arg)
3924 {
3925  HeapTuple tuple;
3926  Form_pg_class form;
3927 
3928  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
3929  if (!HeapTupleIsValid(tuple))
3930  return; /* concurrently dropped */
3931  form = (Form_pg_class) GETSTRUCT(tuple);
3932  renameatt_check(relid, form, false);
3933  ReleaseSysCache(tuple);
3934 }
3935 
3936 /*
3937  * renameatt - changes the name of an attribute in a relation
3938  *
3939  * The returned ObjectAddress is that of the renamed column.
3940  */
3943 {
3944  Oid relid;
3946  ObjectAddress address;
3947 
3948  /* lock level taken here should match renameatt_internal */
3950  stmt->missing_ok ? RVR_MISSING_OK : 0,
3952  NULL);
3953 
3954  if (!OidIsValid(relid))
3955  {
3956  ereport(NOTICE,
3957  (errmsg("relation \"%s\" does not exist, skipping",
3958  stmt->relation->relname)));
3959  return InvalidObjectAddress;
3960  }
3961 
3962  attnum =
3963  renameatt_internal(relid,
3964  stmt->subname, /* old att name */
3965  stmt->newname, /* new att name */
3966  stmt->relation->inh, /* recursive? */
3967  false, /* recursing? */
3968  0, /* expected inhcount */
3969  stmt->behavior);
3970 
3971  ObjectAddressSubSet(address, RelationRelationId, relid, attnum);
3972 
3973  return address;
3974 }
3975 
3976 /*
3977  * same logic as renameatt_internal
3978  */
3979 static ObjectAddress
3981  Oid mytypid,
3982  const char *oldconname,
3983  const char *newconname,
3984  bool recurse,
3985  bool recursing,
3986  int expected_parents)
3987 {
3988  Relation targetrelation = NULL;
3989  Oid constraintOid;
3990  HeapTuple tuple;
3991  Form_pg_constraint con;
3992  ObjectAddress address;
3993 
3994  Assert(!myrelid || !mytypid);
3995 
3996  if (mytypid)
3997  {
3998  constraintOid = get_domain_constraint_oid(mytypid, oldconname, false);
3999  }
4000  else
4001  {
4002  targetrelation = relation_open(myrelid, AccessExclusiveLock);
4003 
4004  /*
4005  * don't tell it whether we're recursing; we allow changing typed
4006  * tables here
4007  */
4008  renameatt_check(myrelid, RelationGetForm(targetrelation), false);
4009 
4010  constraintOid = get_relation_constraint_oid(myrelid, oldconname, false);
4011  }
4012 
4013  tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintOid));
4014  if (!HeapTupleIsValid(tuple))
4015  elog(ERROR, "cache lookup failed for constraint %u",
4016  constraintOid);
4017  con = (Form_pg_constraint) GETSTRUCT(tuple);
4018 
4019  if (myrelid &&
4020  (con->contype == CONSTRAINT_CHECK ||
4021  con->contype == CONSTRAINT_NOTNULL) &&
4022  !con->connoinherit)
4023  {
4024  if (recurse)
4025  {
4026  List *child_oids,
4027  *child_numparents;
4028  ListCell *lo,
4029  *li;
4030 
4031  child_oids = find_all_inheritors(myrelid, AccessExclusiveLock,
4032  &child_numparents);
4033 
4034  forboth(lo, child_oids, li, child_numparents)
4035  {
4036  Oid childrelid = lfirst_oid(lo);
4037  int numparents = lfirst_int(li);
4038 
4039  if (childrelid == myrelid)
4040  continue;
4041 
4042  rename_constraint_internal(childrelid, InvalidOid, oldconname, newconname, false, true, numparents);
4043  }
4044  }
4045  else
4046  {
4047  if (expected_parents == 0 &&
4048  find_inheritance_children(myrelid, NoLock) != NIL)
4049  ereport(ERROR,
4050  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
4051  errmsg("inherited constraint \"%s\" must be renamed in child tables too",
4052  oldconname)));
4053  }
4054 
4055  if (con->coninhcount > expected_parents)
4056  ereport(ERROR,
4057  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
4058  errmsg("cannot rename inherited constraint \"%s\"",
4059  oldconname)));
4060  }
4061 
4062  if (con->conindid
4063  && (con->contype == CONSTRAINT_PRIMARY
4064  || con->contype == CONSTRAINT_UNIQUE
4065  || con->contype == CONSTRAINT_EXCLUSION))
4066  /* rename the index; this renames the constraint as well */
4067  RenameRelationInternal(con->conindid, newconname, false, true);
4068  else
4069  RenameConstraintById(constraintOid, newconname);
4070 
4071  ObjectAddressSet(address, ConstraintRelationId, constraintOid);
4072 
4073  ReleaseSysCache(tuple);
4074 
4075  if (targetrelation)
4076  {
4077  /*
4078  * Invalidate relcache so as others can see the new constraint name.
4079  */
4080  CacheInvalidateRelcache(targetrelation);
4081 
4082  relation_close(targetrelation, NoLock); /* close rel but keep lock */
4083  }
4084 
4085  return address;
4086 }
4087 
4090 {
4091  Oid relid = InvalidOid;
4092  Oid typid = InvalidOid;
4093 
4094  if (stmt->renameType == OBJECT_DOMCONSTRAINT)
4095  {
4096  Relation rel;
4097  HeapTuple tup;
4098 
4099  typid = typenameTypeId(NULL, makeTypeNameFromNameList(castNode(List, stmt->object)));
4100  rel = table_open(TypeRelationId, RowExclusiveLock);
4101  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
4102  if (!HeapTupleIsValid(tup))
4103  elog(ERROR, "cache lookup failed for type %u", typid);
4104  checkDomainOwner(tup);
4105  ReleaseSysCache(tup);
4106  table_close(rel, NoLock);
4107  }
4108  else
4109  {
4110  /* lock level taken here should match rename_constraint_internal */
4112  stmt->missing_ok ? RVR_MISSING_OK : 0,
4114  NULL);
4115  if (!OidIsValid(relid))
4116  {
4117  ereport(NOTICE,
4118  (errmsg("relation \"%s\" does not exist, skipping",
4119  stmt->relation->relname)));
4120  return InvalidObjectAddress;
4121  }
4122  }
4123 
4124  return
4125  rename_constraint_internal(relid, typid,
4126  stmt->subname,
4127  stmt->newname,
4128  (stmt->relation &&
4129  stmt->relation->inh), /* recursive? */
4130  false, /* recursing? */
4131  0 /* expected inhcount */ );
4132 }
4133 
4134 /*
4135  * Execute ALTER TABLE/INDEX/SEQUENCE/VIEW/MATERIALIZED VIEW/FOREIGN TABLE
4136  * RENAME
4137  */
4140 {
4141  bool is_index_stmt = stmt->renameType == OBJECT_INDEX;
4142  Oid relid;
4143  ObjectAddress address;
4144 
4145  /*
4146  * Grab an exclusive lock on the target table, index, sequence, view,
4147  * materialized view, or foreign table, which we will NOT release until
4148  * end of transaction.
4149  *
4150  * Lock level used here should match RenameRelationInternal, to avoid lock
4151  * escalation. However, because ALTER INDEX can be used with any relation
4152  * type, we mustn't believe without verification.
4153  */
4154  for (;;)
4155  {
4156  LOCKMODE lockmode;
4157  char relkind;
4158  bool obj_is_index;
4159 
4160  lockmode = is_index_stmt ? ShareUpdateExclusiveLock : AccessExclusiveLock;
4161 
4162  relid = RangeVarGetRelidExtended(stmt->relation, lockmode,
4163  stmt->missing_ok ? RVR_MISSING_OK : 0,
4165  (void *) stmt);
4166 
4167  if (!OidIsValid(relid))
4168  {
4169  ereport(NOTICE,
4170  (errmsg("relation \"%s\" does not exist, skipping",
4171  stmt->relation->relname)));
4172  return InvalidObjectAddress;
4173  }
4174 
4175  /*
4176  * We allow mismatched statement and object types (e.g., ALTER INDEX
4177  * to rename a table), but we might've used the wrong lock level. If
4178  * that happens, retry with the correct lock level. We don't bother
4179  * if we already acquired AccessExclusiveLock with an index, however.
4180  */
4181  relkind = get_rel_relkind(relid);
4182  obj_is_index = (relkind == RELKIND_INDEX ||
4183  relkind == RELKIND_PARTITIONED_INDEX);
4184  if (obj_is_index || is_index_stmt == obj_is_index)
4185  break;
4186 
4187  UnlockRelationOid(relid, lockmode);
4188  is_index_stmt = obj_is_index;
4189  }
4190 
4191  /* Do the work */
4192  RenameRelationInternal(relid, stmt->newname, false, is_index_stmt);
4193 
4194  ObjectAddressSet(address, RelationRelationId, relid);
4195 
4196  return address;
4197 }
4198 
4199 /*
4200  * RenameRelationInternal - change the name of a relation
4201  */
4202 void
4203 RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bool is_index)
4204 {
4205  Relation targetrelation;
4206  Relation relrelation; /* for RELATION relation */
4207  HeapTuple reltup;
4208  Form_pg_class relform;
4209  Oid namespaceId;
4210 
4211  /*
4212  * Grab a lock on the target relation, which we will NOT release until end
4213  * of transaction. We need at least a self-exclusive lock so that
4214  * concurrent DDL doesn't overwrite the rename if they start updating
4215  * while still seeing the old version. The lock also guards against
4216  * triggering relcache reloads in concurrent sessions, which might not
4217  * handle this information changing under them. For indexes, we can use a
4218  * reduced lock level because RelationReloadIndexInfo() handles indexes
4219  * specially.
4220  */
4221  targetrelation = relation_open(myrelid, is_index ? ShareUpdateExclusiveLock : AccessExclusiveLock);
4222  namespaceId = RelationGetNamespace(targetrelation);
4223 
4224  /*
4225  * Find relation's pg_class tuple, and make sure newrelname isn't in use.
4226  */
4227  relrelation = table_open(RelationRelationId, RowExclusiveLock);
4228 
4229  reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
4230  if (!HeapTupleIsValid(reltup)) /* shouldn't happen */
4231  elog(ERROR, "cache lookup failed for relation %u", myrelid);
4232  relform = (Form_pg_class) GETSTRUCT(reltup);
4233 
4234  if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
4235  ereport(ERROR,
4236  (errcode(ERRCODE_DUPLICATE_TABLE),
4237  errmsg("relation \"%s\" already exists",
4238  newrelname)));
4239 
4240  /*
4241  * RenameRelation is careful not to believe the caller's idea of the
4242  * relation kind being handled. We don't have to worry about this, but
4243  * let's not be totally oblivious to it. We can process an index as
4244  * not-an-index, but not the other way around.
4245  */
4246  Assert(!is_index ||
4247  is_index == (targetrelation->rd_rel->relkind == RELKIND_INDEX ||
4248  targetrelation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX));
4249 
4250  /*
4251  * Update pg_class tuple with new relname. (Scribbling on reltup is OK
4252  * because it's a copy...)
4253  */
4254  namestrcpy(&(relform->relname), newrelname);
4255 
4256  CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
4257 
4258  InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0,
4259  InvalidOid, is_internal);
4260 
4261  heap_freetuple(reltup);
4262  table_close(relrelation, RowExclusiveLock);
4263 
4264  /*
4265  * Also rename the associated type, if any.
4266  */
4267  if (OidIsValid(targetrelation->rd_rel->reltype))
4268  RenameTypeInternal(targetrelation->rd_rel->reltype,
4269  newrelname, namespaceId);
4270 
4271  /*
4272  * Also rename the associated constraint, if any.
4273  */
4274  if (targetrelation->rd_rel->relkind == RELKIND_INDEX ||
4275  targetrelation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
4276  {
4277  Oid constraintId = get_index_constraint(myrelid);
4278 
4279  if (OidIsValid(constraintId))
4280  RenameConstraintById(constraintId, newrelname);
4281  }
4282 
4283  /*
4284  * Close rel, but keep lock!
4285  */
4286  relation_close(targetrelation, NoLock);
4287 }
4288 
4289 /*
4290  * ResetRelRewrite - reset relrewrite
4291  */
4292 void
4294 {
4295  Relation relrelation; /* for RELATION relation */
4296  HeapTuple reltup;
4297  Form_pg_class relform;
4298 
4299  /*
4300  * Find relation's pg_class tuple.
4301  */
4302  relrelation = table_open(RelationRelationId, RowExclusiveLock);
4303 
4304  reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
4305  if (!HeapTupleIsValid(reltup)) /* shouldn't happen */
4306  elog(ERROR, "cache lookup failed for relation %u", myrelid);
4307  relform = (Form_pg_class) GETSTRUCT(reltup);
4308 
4309  /*
4310  * Update pg_class tuple.
4311  */
4312  relform->relrewrite = InvalidOid;
4313 
4314  CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
4315 
4316  heap_freetuple(reltup);
4317  table_close(relrelation, RowExclusiveLock);
4318 }
4319 
4320 /*
4321  * Disallow ALTER TABLE (and similar commands) when the current backend has
4322  * any open reference to the target table besides the one just acquired by
4323  * the calling command; this implies there's an open cursor or active plan.
4324  * We need this check because our lock doesn't protect us against stomping
4325  * on our own foot, only other people's feet!
4326  *
4327  * For ALTER TABLE, the only case known to cause serious trouble is ALTER
4328  * COLUMN TYPE, and some changes are obviously pretty benign, so this could
4329  * possibly be relaxed to only error out for certain types of alterations.
4330  * But the use-case for allowing any of these things is not obvious, so we
4331  * won't work hard at it for now.
4332  *
4333  * We also reject these commands if there are any pending AFTER trigger events
4334  * for the rel. This is certainly necessary for the rewriting variants of
4335  * ALTER TABLE, because they don't preserve tuple TIDs and so the pending
4336  * events would try to fetch the wrong tuples. It might be overly cautious
4337  * in other cases, but again it seems better to err on the side of paranoia.
4338  *
4339  * REINDEX calls this with "rel" referencing the index to be rebuilt; here
4340  * we are worried about active indexscans on the index. The trigger-event
4341  * check can be skipped, since we are doing no damage to the parent table.
4342  *
4343  * The statement name (eg, "ALTER TABLE") is passed for use in error messages.
4344  */
4345 void
4347 {
4348  int expected_refcnt;
4349 
4350  expected_refcnt = rel->rd_isnailed ? 2 : 1;
4351  if (rel->rd_refcnt != expected_refcnt)
4352  ereport(ERROR,
4353  (errcode(ERRCODE_OBJECT_IN_USE),
4354  /* translator: first %s is a SQL command, eg ALTER TABLE */
4355  errmsg("cannot %s \"%s\" because it is being used by active queries in this session",
4356  stmt, RelationGetRelationName(rel))));
4357 
4358  if (rel->rd_rel->relkind != RELKIND_INDEX &&
4359  rel->rd_rel->relkind != RELKIND_PARTITIONED_INDEX &&
4361  ereport(ERROR,
4362  (errcode(ERRCODE_OBJECT_IN_USE),
4363  /* translator: first %s is a SQL command, eg ALTER TABLE */
4364  errmsg("cannot %s \"%s\" because it has pending trigger events",
4365  stmt, RelationGetRelationName(rel))));
4366 }
4367 
4368 /*
4369  * AlterTableLookupRelation
4370  * Look up, and lock, the OID for the relation named by an alter table
4371  * statement.
4372  */
4373 Oid
4375 {
4376  return RangeVarGetRelidExtended(stmt->relation, lockmode,
4377  stmt->missing_ok ? RVR_MISSING_OK : 0,
4379  (void *) stmt);
4380 }
4381 
4382 /*
4383  * AlterTable
4384  * Execute ALTER TABLE, which can be a list of subcommands
4385  *
4386  * ALTER TABLE is performed in three phases:
4387  * 1. Examine subcommands and perform pre-transformation checking.
4388  * 2. Validate and transform subcommands, and update system catalogs.
4389  * 3. Scan table(s) to check new constraints, and optionally recopy
4390  * the data into new table(s).
4391  * Phase 3 is not performed unless one or more of the subcommands requires
4392  * it. The intention of this design is to allow multiple independent
4393  * updates of the table schema to be performed with only one pass over the
4394  * data.
4395  *
4396  * ATPrepCmd performs phase 1. A "work queue" entry is created for
4397  * each table to be affected (there may be multiple affected tables if the
4398  * commands traverse a table inheritance hierarchy). Also we do preliminary
4399  * validation of the subcommands. Because earlier subcommands may change
4400  * the catalog state seen by later commands, there are limits to what can
4401  * be done in this phase. Generally, this phase acquires table locks,
4402  * checks permissions and relkind, and recurses to find child tables.
4403  *
4404  * ATRewriteCatalogs performs phase 2 for each affected table.
4405  * Certain subcommands need to be performed before others to avoid
4406  * unnecessary conflicts; for example, DROP COLUMN should come before
4407  * ADD COLUMN. Therefore phase 1 divides the subcommands into multiple
4408  * lists, one for each logical "pass" of phase 2.
4409  *
4410  * ATRewriteTables performs phase 3 for those tables that need it.
4411  *
4412  * For most subcommand types, phases 2 and 3 do no explicit recursion,
4413  * since phase 1 already does it. However, for certain subcommand types
4414  * it is only possible to determine how to recurse at phase 2 time; for
4415  * those cases, phase 1 sets the cmd->recurse flag.
4416  *
4417  * Thanks to the magic of MVCC, an error anywhere along the way rolls back
4418  * the whole operation; we don't have to do anything special to clean up.
4419  *
4420  * The caller must lock the relation, with an appropriate lock level
4421  * for the subcommands requested, using AlterTableGetLockLevel(stmt->cmds)
4422  * or higher. We pass the lock level down
4423  * so that we can apply it recursively to inherited tables. Note that the
4424  * lock level we want as we recurse might well be higher than required for
4425  * that specific subcommand. So we pass down the overall lock requirement,
4426  * rather than reassess it at lower levels.
4427  *
4428  * The caller also provides a "context" which is to be passed back to
4429  * utility.c when we need to execute a subcommand such as CREATE INDEX.
4430  * Some of the fields therein, such as the relid, are used here as well.
4431  */
4432 void
4435 {
4436  Relation rel;
4437 
4438  /* Caller is required to provide an adequate lock. */
4439  rel = relation_open(context->relid, NoLock);
4440 
4441  CheckTableNotInUse(rel, "ALTER TABLE");
4442 
4443  ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode, context);
4444 }
4445 
4446 /*
4447  * AlterTableInternal
4448  *
4449  * ALTER TABLE with target specified by OID
4450  *
4451  * We do not reject if the relation is already open, because it's quite
4452  * likely that one or more layers of caller have it open. That means it
4453  * is unsafe to use this entry point for alterations that could break
4454  * existing query plans. On the assumption it's not used for such, we
4455  * don't have to reject pending AFTER triggers, either.
4456  *
4457  * Also, since we don't have an AlterTableUtilityContext, this cannot be
4458  * used for any subcommand types that require parse transformation or
4459  * could generate subcommands that have to be passed to ProcessUtility.
4460  */
4461 void
4462 AlterTableInternal(Oid relid, List *cmds, bool recurse)
4463 {
4464  Relation rel;
4465  LOCKMODE lockmode = AlterTableGetLockLevel(cmds);
4466 
4467  rel = relation_open(relid, lockmode);
4468 
4470 
4471  ATController(NULL, rel, cmds, recurse, lockmode, NULL);
4472 }
4473 
4474 /*
4475  * AlterTableGetLockLevel
4476  *
4477  * Sets the overall lock level required for the supplied list of subcommands.
4478  * Policy for doing this set according to needs of AlterTable(), see
4479  * comments there for overall explanation.
4480  *
4481  * Function is called before and after parsing, so it must give same
4482  * answer each time it is called. Some subcommands are transformed
4483  * into other subcommand types, so the transform must never be made to a
4484  * lower lock level than previously assigned. All transforms are noted below.
4485  *
4486  * Since this is called before we lock the table we cannot use table metadata
4487  * to influence the type of lock we acquire.
4488  *
4489  * There should be no lockmodes hardcoded into the subcommand functions. All
4490  * lockmode decisions for ALTER TABLE are made here only. The one exception is
4491  * ALTER TABLE RENAME which is treated as a different statement type T_RenameStmt
4492  * and does not travel through this section of code and cannot be combined with
4493  * any of the subcommands given here.
4494  *
4495  * Note that Hot Standby only knows about AccessExclusiveLocks on the primary
4496  * so any changes that might affect SELECTs running on standbys need to use
4497  * AccessExclusiveLocks even if you think a lesser lock would do, unless you
4498  * have a solution for that also.
4499  *
4500  * Also note that pg_dump uses only an AccessShareLock, meaning that anything
4501  * that takes a lock less than AccessExclusiveLock can change object definitions
4502  * while pg_dump is running. Be careful to check that the appropriate data is
4503  * derived by pg_dump using an MVCC snapshot, rather than syscache lookups,
4504  * otherwise we might end up with an inconsistent dump that can't restore.
4505  */
4506 LOCKMODE
4508 {
4509  /*
4510  * This only works if we read catalog tables using MVCC snapshots.
4511  */
4512  ListCell *lcmd;
4514 
4515  foreach(lcmd, cmds)
4516  {
4517  AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
4518  LOCKMODE cmd_lockmode = AccessExclusiveLock; /* default for compiler */
4519 
4520  switch (cmd->subtype)
4521  {
4522  /*
4523  * These subcommands rewrite the heap, so require full locks.
4524  */
4525  case AT_AddColumn: /* may rewrite heap, in some cases and visible
4526  * to SELECT */
4527  case AT_SetAccessMethod: /* must rewrite heap */
4528  case AT_SetTableSpace: /* must rewrite heap */
4529  case AT_AlterColumnType: /* must rewrite heap */
4530  cmd_lockmode = AccessExclusiveLock;
4531  break;
4532 
4533  /*
4534  * These subcommands may require addition of toast tables. If
4535  * we add a toast table to a table currently being scanned, we
4536  * might miss data added to the new toast table by concurrent
4537  * insert transactions.
4538  */
4539  case AT_SetStorage: /* may add toast tables, see
4540  * ATRewriteCatalogs() */
4541  cmd_lockmode = AccessExclusiveLock;
4542  break;
4543 
4544  /*
4545  * Removing constraints can affect SELECTs that have been
4546  * optimized assuming the constraint holds true. See also
4547  * CloneFkReferenced.
4548  */
4549  case AT_DropConstraint: /* as DROP INDEX */
4550  case AT_DropNotNull: /* may change some SQL plans */
4551  cmd_lockmode = AccessExclusiveLock;
4552  break;
4553 
4554  /*
4555  * Subcommands that may be visible to concurrent SELECTs
4556  */
4557  case AT_DropColumn: /* change visible to SELECT */
4558  case AT_AddColumnToView: /* CREATE VIEW */
4559  case AT_DropOids: /* used to equiv to DropColumn */
4560  case AT_EnableAlwaysRule: /* may change SELECT rules */
4561  case AT_EnableReplicaRule: /* may change SELECT rules */
4562  case AT_EnableRule: /* may change SELECT rules */
4563  case AT_DisableRule: /* may change SELECT rules */
4564  cmd_lockmode = AccessExclusiveLock;
4565  break;
4566 
4567  /*
4568  * Changing owner may remove implicit SELECT privileges
4569  */
4570  case AT_ChangeOwner: /* change visible to SELECT */
4571  cmd_lockmode = AccessExclusiveLock;
4572  break;
4573 
4574  /*
4575  * Changing foreign table options may affect optimization.
4576  */
4577  case AT_GenericOptions:
4579  cmd_lockmode = AccessExclusiveLock;
4580  break;
4581 
4582  /*
4583  * These subcommands affect write operations only.
4584  */
4585  case AT_EnableTrig:
4586  case AT_EnableAlwaysTrig:
4587  case AT_EnableReplicaTrig:
4588  case AT_EnableTrigAll:
4589  case AT_EnableTrigUser:
4590  case AT_DisableTrig:
4591  case AT_DisableTrigAll:
4592  case AT_DisableTrigUser:
4593  cmd_lockmode = ShareRowExclusiveLock;
4594  break;
4595 
4596  /*
4597  * These subcommands affect write operations only. XXX
4598  * Theoretically, these could be ShareRowExclusiveLock.
4599  */
4600  case AT_ColumnDefault:
4602  case AT_AlterConstraint:
4603  case AT_AddIndex: /* from ADD CONSTRAINT */
4604  case AT_AddIndexConstraint:
4605  case AT_ReplicaIdentity:
4606  case AT_SetNotNull:
4607  case AT_SetAttNotNull:
4608  case AT_EnableRowSecurity:
4609  case AT_DisableRowSecurity:
4610  case AT_ForceRowSecurity:
4611  case AT_NoForceRowSecurity:
4612  case AT_AddIdentity:
4613  case AT_DropIdentity:
4614  case AT_SetIdentity:
4615  case AT_SetExpression:
4616  case AT_DropExpression:
4617  case AT_SetCompression:
4618  cmd_lockmode = AccessExclusiveLock;
4619  break;
4620 
4621  case AT_AddConstraint:
4622  case AT_ReAddConstraint: /* becomes AT_AddConstraint */
4623  case AT_ReAddDomainConstraint: /* becomes AT_AddConstraint */
4624  if (IsA(cmd->def, Constraint))
4625  {
4626  Constraint *con = (Constraint *) cmd->def;
4627 
4628  switch (con->contype)
4629  {
4630  case CONSTR_EXCLUSION:
4631  case CONSTR_PRIMARY:
4632  case CONSTR_UNIQUE:
4633 
4634  /*
4635  * Cases essentially the same as CREATE INDEX. We
4636  * could reduce the lock strength to ShareLock if
4637  * we can work out how to allow concurrent catalog
4638  * updates. XXX Might be set down to
4639  * ShareRowExclusiveLock but requires further
4640  * analysis.
4641  */
4642  cmd_lockmode = AccessExclusiveLock;
4643  break;
4644  case CONSTR_FOREIGN:
4645 
4646  /*
4647  * We add triggers to both tables when we add a
4648  * Foreign Key, so the lock level must be at least
4649  * as strong as CREATE TRIGGER.
4650  */
4651  cmd_lockmode = ShareRowExclusiveLock;
4652  break;
4653 
4654  default:
4655  cmd_lockmode = AccessExclusiveLock;
4656  }
4657  }
4658  break;
4659 
4660  /*
4661  * These subcommands affect inheritance behaviour. Queries
4662  * started before us will continue to see the old inheritance
4663  * behaviour, while queries started after we commit will see
4664  * new behaviour. No need to prevent reads or writes to the
4665  * subtable while we hook it up though. Changing the TupDesc
4666  * may be a problem, so keep highest lock.
4667  */
4668  case AT_AddInherit:
4669  case AT_DropInherit:
4670  cmd_lockmode = AccessExclusiveLock;
4671  break;
4672 
4673  /*
4674  * These subcommands affect implicit row type conversion. They
4675  * have affects similar to CREATE/DROP CAST on queries. don't
4676  * provide for invalidating parse trees as a result of such
4677  * changes, so we keep these at AccessExclusiveLock.
4678  */
4679  case AT_AddOf:
4680  case AT_DropOf:
4681  cmd_lockmode = AccessExclusiveLock;
4682  break;
4683 
4684  /*
4685  * Only used by CREATE OR REPLACE VIEW which must conflict
4686  * with an SELECTs currently using the view.
4687  */
4688  case AT_ReplaceRelOptions:
4689  cmd_lockmode = AccessExclusiveLock;
4690  break;
4691 
4692  /*
4693  * These subcommands affect general strategies for performance
4694  * and maintenance, though don't change the semantic results
4695  * from normal data reads and writes. Delaying an ALTER TABLE
4696  * behind currently active writes only delays the point where
4697  * the new strategy begins to take effect, so there is no
4698  * benefit in waiting. In this case the minimum restriction
4699  * applies: we don't currently allow concurrent catalog
4700  * updates.
4701  */
4702  case AT_SetStatistics: /* Uses MVCC in getTableAttrs() */
4703  case AT_ClusterOn: /* Uses MVCC in getIndexes() */
4704  case AT_DropCluster: /* Uses MVCC in getIndexes() */
4705  case AT_SetOptions: /* Uses MVCC in getTableAttrs() */
4706  case AT_ResetOptions: /* Uses MVCC in getTableAttrs() */
4707  cmd_lockmode = ShareUpdateExclusiveLock;
4708  break;
4709 
4710  case AT_SetLogged:
4711  case AT_SetUnLogged:
4712  cmd_lockmode = AccessExclusiveLock;
4713  break;
4714 
4715  case AT_ValidateConstraint: /* Uses MVCC in getConstraints() */
4716  cmd_lockmode = ShareUpdateExclusiveLock;
4717  break;
4718 
4719  /*
4720  * Rel options are more complex than first appears. Options
4721  * are set here for tables, views and indexes; for historical
4722  * reasons these can all be used with ALTER TABLE, so we can't
4723  * decide between them using the basic grammar.
4724  */
4725  case AT_SetRelOptions: /* Uses MVCC in getIndexes() and
4726  * getTables() */
4727  case AT_ResetRelOptions: /* Uses MVCC in getIndexes() and
4728  * getTables() */
4729  cmd_lockmode = AlterTableGetRelOptionsLockLevel((List *) cmd->def);
4730  break;
4731 
4732  case AT_AttachPartition:
4733  cmd_lockmode = ShareUpdateExclusiveLock;
4734  break;
4735 
4736  case AT_DetachPartition:
4737  if (((PartitionCmd *) cmd->def)->concurrent)
4738  cmd_lockmode = ShareUpdateExclusiveLock;
4739  else
4740  cmd_lockmode = AccessExclusiveLock;
4741  break;
4742 
4744  cmd_lockmode = ShareUpdateExclusiveLock;
4745  break;
4746 
4747  case AT_SplitPartition:
4748  cmd_lockmode = AccessExclusiveLock;
4749  break;
4750 
4751  case AT_MergePartitions:
4752  cmd_lockmode = AccessExclusiveLock;
4753  break;
4754 
4755  default: /* oops */
4756  elog(ERROR, "unrecognized alter table type: %d",
4757  (int) cmd->subtype);
4758  break;
4759  }
4760 
4761  /*
4762  * Take the greatest lockmode from any subcommand
4763  */
4764  if (cmd_lockmode > lockmode)
4765  lockmode = cmd_lockmode;
4766  }
4767 
4768  return lockmode;
4769 }
4770 
4771 /*
4772  * ATController provides top level control over the phases.
4773  *
4774  * parsetree is passed in to allow it to be passed to event triggers
4775  * when requested.
4776  */
4777 static void
4779  Relation rel, List *cmds, bool recurse, LOCKMODE lockmode,
4781 {
4782  List *wqueue = NIL;
4783  ListCell *lcmd;
4784 
4785  /* Phase 1: preliminary examination of commands, create work queue */
4786  foreach(lcmd, cmds)
4787  {
4788  AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
4789 
4790  ATPrepCmd(&wqueue, rel, cmd, recurse, false, lockmode, context);
4791  }
4792 
4793  /* Close the relation, but keep lock until commit */
4794  relation_close(rel, NoLock);
4795 
4796  /* Phase 2: update system catalogs */
4797  ATRewriteCatalogs(&wqueue, lockmode, context);
4798 
4799  /* Phase 3: scan/rewrite tables as needed, and run afterStmts */
4800  ATRewriteTables(parsetree, &wqueue, lockmode, context);
4801 }
4802 
4803 /*
4804  * ATPrepCmd
4805  *
4806  * Traffic cop for ALTER TABLE Phase 1 operations, including simple
4807  * recursion and permission checks.
4808  *
4809  * Caller must have acquired appropriate lock type on relation already.
4810  * This lock should be held until commit.
4811  */
4812 static void
4813 ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
4814  bool recurse, bool recursing, LOCKMODE lockmode,
4816 {
4817  AlteredTableInfo *tab;
4819 
4820  /* Find or create work queue entry for this table */
4821  tab = ATGetQueueEntry(wqueue, rel);
4822 
4823  /*
4824  * Disallow any ALTER TABLE other than ALTER TABLE DETACH FINALIZE on
4825  * partitions that are pending detach.
4826  */
4827  if (rel->rd_rel->relispartition &&
4830  ereport(ERROR,
4831  errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
4832  errmsg("cannot alter partition \"%s\" with an incomplete detach",
4834  errhint("Use ALTER TABLE ... DETACH PARTITION ... FINALIZE to complete the pending detach operation."));
4835 
4836  /*
4837  * Copy the original subcommand for each table, so we can scribble on it.
4838  * This avoids conflicts when different child tables need to make
4839  * different parse transformations (for example, the same column may have
4840  * different column numbers in different children).
4841  */
4842  cmd = copyObject(cmd);
4843 
4844  /*
4845  * Do permissions and relkind checking, recursion to child tables if
4846  * needed, and any additional phase-1 processing needed. (But beware of
4847  * adding any processing that looks at table details that another
4848  * subcommand could change. In some cases we reject multiple subcommands
4849  * that could try to change the same state in contrary ways.)
4850  */
4851  switch (cmd->subtype)
4852  {
4853  case AT_AddColumn: /* ADD COLUMN */
4854  ATSimplePermissions(cmd->subtype, rel,
4856  ATPrepAddColumn(wqueue, rel, recurse, recursing, false, cmd,
4857  lockmode, context);
4858  /* Recursion occurs during execution phase */
4859  pass = AT_PASS_ADD_COL;
4860  break;
4861  case AT_AddColumnToView: /* add column via CREATE OR REPLACE VIEW */
4862  ATSimplePermissions(cmd->subtype, rel, ATT_VIEW);
4863  ATPrepAddColumn(wqueue, rel, recurse, recursing, true, cmd,
4864  lockmode, context);
4865  /* Recursion occurs during execution phase */
4866  pass = AT_PASS_ADD_COL;
4867  break;
4868  case AT_ColumnDefault: /* ALTER COLUMN DEFAULT */
4869 
4870  /*
4871  * We allow defaults on views so that INSERT into a view can have
4872  * default-ish behavior. This works because the rewriter
4873  * substitutes default values into INSERTs before it expands
4874  * rules.
4875  */
4877  ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4878  /* No command-specific prep needed */
4879  pass = cmd->def ? AT_PASS_ADD_OTHERCONSTR : AT_PASS_DROP;
4880  break;
4881  case AT_CookedColumnDefault: /* add a pre-cooked default */
4882  /* This is currently used only in CREATE TABLE */
4883  /* (so the permission check really isn't necessary) */
4885  /* This command never recurses */
4886  pass = AT_PASS_ADD_OTHERCONSTR;
4887  break;
4888  case AT_AddIdentity:
4890  /* Set up recursion for phase 2; no other prep needed */
4891  if (recurse)
4892  cmd->recurse = true;
4893  pass = AT_PASS_ADD_OTHERCONSTR;
4894  break;
4895  case AT_SetIdentity:
4897  /* Set up recursion for phase 2; no other prep needed */
4898  if (recurse)
4899  cmd->recurse = true;
4900  /* This should run after AddIdentity, so do it in MISC pass */
4901  pass = AT_PASS_MISC;
4902  break;
4903  case AT_DropIdentity:
4905  /* Set up recursion for phase 2; no other prep needed */
4906  if (recurse)
4907  cmd->recurse = true;
4908  pass = AT_PASS_DROP;
4909  break;
4910  case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
4912  /* Set up recursion for phase 2; no other prep needed */
4913  if (recurse)
4914  cmd->recurse = true;
4915  pass = AT_PASS_DROP;
4916  break;
4917  case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */
4919  /* Set up recursion for phase 2; no other prep needed */
4920  if (recurse)
4921  cmd->recurse = true;
4922  pass = AT_PASS_COL_ATTRS;
4923  break;
4924  case AT_SetAttNotNull: /* set pg_attribute.attnotnull without adding
4925  * a constraint */
4927  /* Need command-specific recursion decision */
4928  ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4929  pass = AT_PASS_COL_ATTRS;
4930  break;
4931  case AT_SetExpression: /* ALTER COLUMN SET EXPRESSION */
4933  ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4934  pass = AT_PASS_SET_EXPRESSION;
4935  break;
4936  case AT_DropExpression: /* ALTER COLUMN DROP EXPRESSION */
4938  ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4939  ATPrepDropExpression(rel, cmd, recurse, recursing, lockmode);
4940  pass = AT_PASS_DROP;
4941  break;
4942  case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */
4944  ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4945  /* No command-specific prep needed */
4946  pass = AT_PASS_MISC;
4947  break;
4948  case AT_SetOptions: /* ALTER COLUMN SET ( options ) */
4949  case AT_ResetOptions: /* ALTER COLUMN RESET ( options ) */
4951  /* This command never recurses */
4952  pass = AT_PASS_MISC;
4953  break;
4954  case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
4956  ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context);
4957  /* No command-specific prep needed */
4958  pass = AT_PASS_MISC;
4959  break;
4960  case AT_SetCompression: /* ALTER COLUMN SET COMPRESSION */
4962  /* This command never recurses */
4963  /* No command-specific prep needed */
4964  pass = AT_PASS_MISC;
4965  break;
4966  case AT_DropColumn: /* DROP COLUMN */
4967  ATSimplePermissions(cmd->subtype, rel,
4969  ATPrepDropColumn(wqueue, rel, recurse, recursing, cmd,
4970  lockmode, context);
4971  /* Recursion occurs during execution phase */
4972  pass = AT_PASS_DROP;
4973  break;
4974  case AT_AddIndex: /* ADD INDEX */
4976  /* This command never recurses */
4977  /* No command-specific prep needed */
4978  pass = AT_PASS_ADD_INDEX;
4979  break;
4980  case AT_AddConstraint: /* ADD CONSTRAINT */
4982  /* Recursion occurs during execution phase */
4983  /* No command-specific prep needed except saving recurse flag */
4984  if (recurse)
4985  cmd->recurse = true;
4986  pass = AT_PASS_ADD_CONSTR;
4987  break;
4988  case AT_AddIndexConstraint: /* ADD CONSTRAINT USING INDEX */
4990  /* This command never recurses */
4991  /* No command-specific prep needed */
4992  pass = AT_PASS_ADD_INDEXCONSTR;
4993  break;
4994  case AT_DropConstraint: /* DROP CONSTRAINT */
4996  ATCheckPartitionsNotInUse(rel, lockmode);
4997  /* Other recursion occurs during execution phase */
4998  /* No command-specific prep needed except saving recurse flag */
4999  if (recurse)
5000  cmd->recurse = true;
5001  pass = AT_PASS_DROP;
5002  break;
5003  case AT_AlterColumnType: /* ALTER COLUMN TYPE */
5004  ATSimplePermissions(cmd->subtype, rel,
5006  /* See comments for ATPrepAlterColumnType */
5007  cmd = ATParseTransformCmd(wqueue, tab, rel, cmd, recurse, lockmode,
5009  Assert(cmd != NULL);
5010  /* Performs own recursion */
5011  ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd,
5012  lockmode, context);
5013  pass = AT_PASS_ALTER_TYPE;
5014  break;
5017  /* This command never recurses */
5018  /* No command-specific prep needed */
5019  pass = AT_PASS_MISC;
5020  break;
5021  case AT_ChangeOwner: /* ALTER OWNER */
5022  /* This command never recurses */
5023  /* No command-specific prep needed */
5024  pass = AT_PASS_MISC;
5025  break;
5026  case AT_ClusterOn: /* CLUSTER ON */
5027  case AT_DropCluster: /* SET WITHOUT CLUSTER */
5029  /* These commands never recurse */
5030  /* No command-specific prep needed */
5031  pass = AT_PASS_MISC;
5032  break;
5033  case AT_SetLogged: /* SET LOGGED */
5035  if (tab->chgPersistence)
5036  ereport(ERROR,
5037  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5038  errmsg("cannot change persistence setting twice")));
5039  tab->chgPersistence = ATPrepChangePersistence(rel, true);
5040  /* force rewrite if necessary; see comment in ATRewriteTables */
5041  if (tab->chgPersistence)
5042  {
5044  tab->newrelpersistence = RELPERSISTENCE_PERMANENT;
5045  }
5046  pass = AT_PASS_MISC;
5047  break;
5048  case AT_SetUnLogged: /* SET UNLOGGED */
5050  if (tab->chgPersistence)
5051  ereport(ERROR,
5052  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5053  errmsg("cannot change persistence setting twice")));
5054  tab->chgPersistence = ATPrepChangePersistence(rel, false);
5055  /* force rewrite if necessary; see comment in ATRewriteTables */
5056  if (tab->chgPersistence)
5057  {
5059  tab->newrelpersistence = RELPERSISTENCE_UNLOGGED;
5060  }
5061  pass = AT_PASS_MISC;
5062  break;
5063  case AT_DropOids: /* SET WITHOUT OIDS */
5065  pass = AT_PASS_DROP;
5066  break;
5067  case AT_SetAccessMethod: /* SET ACCESS METHOD */
5069 
5070  /* check if another access method change was already requested */
5071  if (tab->chgAccessMethod)
5072  ereport(ERROR,
5073  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5074  errmsg("cannot have multiple SET ACCESS METHOD subcommands")));
5075 
5076  ATPrepSetAccessMethod(tab, rel, cmd->name);
5077  pass = AT_PASS_MISC; /* does not matter; no work in Phase 2 */
5078  break;
5079  case AT_SetTableSpace: /* SET TABLESPACE */
5082  /* This command never recurses */
5083  ATPrepSetTableSpace(tab, rel, cmd->name, lockmode);
5084  pass = AT_PASS_MISC; /* doesn't actually matter */
5085  break;
5086  case AT_SetRelOptions: /* SET (...) */
5087  case AT_ResetRelOptions: /* RESET (...) */
5088  case AT_ReplaceRelOptions: /* reset them all, then set just these */
5090  /* This command never recurses */
5091  /* No command-specific prep needed */
5092  pass = AT_PASS_MISC;
5093  break;
5094  case AT_AddInherit: /* INHERIT */
5096  /* This command never recurses */
5097  ATPrepAddInherit(rel);
5098  pass = AT_PASS_MISC;
5099  break;
5100  case AT_DropInherit: /* NO INHERIT */
5102  /* This command never recurses */
5103  /* No command-specific prep needed */
5104  pass = AT_PASS_MISC;
5105  break;
5106  case AT_AlterConstraint: /* ALTER CONSTRAINT */
5108  /* Recursion occurs during execution phase */
5109  pass = AT_PASS_MISC;
5110  break;
5111  case AT_ValidateConstraint: /* VALIDATE CONSTRAINT */
5113  /* Recursion occurs during execution phase */
5114  /* No command-specific prep needed except saving recurse flag */
5115  if (recurse)
5116  cmd->recurse = true;
5117  pass = AT_PASS_MISC;
5118  break;
5119  case AT_ReplicaIdentity: /* REPLICA IDENTITY ... */
5121  pass = AT_PASS_MISC;
5122  /* This command never recurses */
5123  /* No command-specific prep needed */
5124  break;
5125  case AT_EnableTrig: /* ENABLE TRIGGER variants */
5126  case AT_EnableAlwaysTrig:
5127  case AT_EnableReplicaTrig:
5128  case AT_EnableTrigAll:
5129  case AT_EnableTrigUser:
5130  case AT_DisableTrig: /* DISABLE TRIGGER variants */
5131  case AT_DisableTrigAll:
5132  case AT_DisableTrigUser:
5134  /* Set up recursion for phase 2; no other prep needed */
5135  if (recurse)
5136  cmd->recurse = true;
5137  pass = AT_PASS_MISC;
5138  break;
5139  case AT_EnableRule: /* ENABLE/DISABLE RULE variants */
5140  case AT_EnableAlwaysRule:
5141  case AT_EnableReplicaRule:
5142  case AT_DisableRule:
5143  case AT_AddOf: /* OF */
5144  case AT_DropOf: /* NOT OF */
5145  case AT_EnableRowSecurity:
5146  case AT_DisableRowSecurity:
5147  case AT_ForceRowSecurity:
5148  case AT_NoForceRowSecurity:
5150  /* These commands never recurse */
5151  /* No command-specific prep needed */
5152  pass = AT_PASS_MISC;
5153  break;
5154  case AT_GenericOptions:
5156  /* No command-specific prep needed */
5157  pass = AT_PASS_MISC;
5158  break;
5159  case AT_AttachPartition:
5161  /* No command-specific prep needed */
5162  pass = AT_PASS_MISC;
5163  break;
5164  case AT_DetachPartition:
5166  /* No command-specific prep needed */
5167  pass = AT_PASS_MISC;
5168  break;
5171  /* No command-specific prep needed */
5172  pass = AT_PASS_MISC;
5173  break;
5174  case AT_SplitPartition:
5176  /* No command-specific prep needed */
5177  pass = AT_PASS_MISC;
5178  break;
5179  case AT_MergePartitions:
5181  /* No command-specific prep needed */
5182  pass = AT_PASS_MISC;
5183  break;
5184  default: /* oops */
5185  elog(ERROR, "unrecognized alter table type: %d",
5186  (int) cmd->subtype);
5187  pass = AT_PASS_UNSET; /* keep compiler quiet */
5188  break;
5189  }
5190  Assert(pass > AT_PASS_UNSET);
5191 
5192  /* Add the subcommand to the appropriate list for phase 2 */
5193  tab->subcmds[pass] = lappend(tab->subcmds[pass], cmd);
5194 }
5195 
5196 /*
5197  * ATRewriteCatalogs
5198  *
5199  * Traffic cop for ALTER TABLE Phase 2 operations. Subcommands are
5200  * dispatched in a "safe" execution order (designed to avoid unnecessary
5201  * conflicts).
5202  */
5203 static void
5204 ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode,
5206 {
5207  ListCell *ltab;
5208 
5209  /*
5210  * We process all the tables "in parallel", one pass at a time. This is
5211  * needed because we may have to propagate work from one table to another
5212  * (specifically, ALTER TYPE on a foreign key's PK has to dispatch the
5213  * re-adding of the foreign key constraint to the other table). Work can
5214  * only be propagated into later passes, however.
5215  */
5216  for (AlterTablePass pass = 0; pass < AT_NUM_PASSES; pass++)
5217  {
5218  /* Go through each table that needs to be processed */
5219  foreach(ltab, *wqueue)
5220  {
5221  AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
5222  List *subcmds = tab->subcmds[pass];
5223  ListCell *lcmd;
5224 
5225  if (subcmds == NIL)
5226  continue;
5227 
5228  /*
5229  * Open the relation and store it in tab. This allows subroutines
5230  * close and reopen, if necessary. Appropriate lock was obtained
5231  * by phase 1, needn't get it again.
5232  */
5233  tab->rel = relation_open(tab->relid, NoLock);
5234 
5235  foreach(lcmd, subcmds)
5236  ATExecCmd(wqueue, tab,
5237  lfirst_node(AlterTableCmd, lcmd),
5238  lockmode, pass, context);
5239 
5240  /*
5241  * After the ALTER TYPE or SET EXPRESSION pass, do cleanup work
5242  * (this is not done in ATExecAlterColumnType since it should be
5243  * done only once if multiple columns of a table are altered).
5244  */
5245  if (pass == AT_PASS_ALTER_TYPE || pass == AT_PASS_SET_EXPRESSION)
5246  ATPostAlterTypeCleanup(wqueue, tab, lockmode);
5247 
5248  if (tab->rel)
5249  {
5250  relation_close(tab->rel, NoLock);
5251  tab->rel = NULL;
5252  }
5253  }
5254  }
5255 
5256  /* Check to see if a toast table must be added. */
5257  foreach(ltab, *wqueue)
5258  {
5259  AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
5260 
5261  /*
5262  * If the table is source table of ATTACH PARTITION command, we did
5263  * not modify anything about it that will change its toasting
5264  * requirement, so no need to check.
5265  */
5266  if (((tab->relkind == RELKIND_RELATION ||
5267  tab->relkind == RELKIND_PARTITIONED_TABLE) &&
5268  tab->partition_constraint == NULL) ||
5269  tab->relkind == RELKIND_MATVIEW)
5270  AlterTableCreateToastTable(tab->relid, (Datum) 0, lockmode);
5271  }
5272 }
5273 
5274 /*
5275  * ATExecCmd: dispatch a subcommand to appropriate execution routine
5276  */
5277 static void
5279  AlterTableCmd *cmd, LOCKMODE lockmode, AlterTablePass cur_pass,
5281 {
5283  Relation rel = tab->rel;
5284 
5285  switch (cmd->subtype)
5286  {
5287  case AT_AddColumn: /* ADD COLUMN */
5288  case AT_AddColumnToView: /* add column via CREATE OR REPLACE VIEW */
5289  address = ATExecAddColumn(wqueue, tab, rel, &cmd,
5290  cmd->recurse, false,
5291  lockmode, cur_pass, context);
5292