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