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