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