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