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