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