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