]> granicus.if.org Git - postgresql/blob - src/backend/commands/tablecmds.c
3b28e8c34f633965920118a73fb5b2f5a026c45b
[postgresql] / src / backend / commands / tablecmds.c
1 /*-------------------------------------------------------------------------
2  *
3  * tablecmds.c
4  *        Commands for creating and altering table structures and settings
5  *
6  * Portions Copyright (c) 1996-2017, 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/genam.h"
18 #include "access/heapam.h"
19 #include "access/multixact.h"
20 #include "access/reloptions.h"
21 #include "access/relscan.h"
22 #include "access/sysattr.h"
23 #include "access/tupconvert.h"
24 #include "access/xact.h"
25 #include "access/xlog.h"
26 #include "catalog/catalog.h"
27 #include "catalog/dependency.h"
28 #include "catalog/heap.h"
29 #include "catalog/index.h"
30 #include "catalog/indexing.h"
31 #include "catalog/namespace.h"
32 #include "catalog/objectaccess.h"
33 #include "catalog/partition.h"
34 #include "catalog/pg_am.h"
35 #include "catalog/pg_collation.h"
36 #include "catalog/pg_constraint.h"
37 #include "catalog/pg_constraint_fn.h"
38 #include "catalog/pg_depend.h"
39 #include "catalog/pg_foreign_table.h"
40 #include "catalog/pg_inherits.h"
41 #include "catalog/pg_inherits_fn.h"
42 #include "catalog/pg_namespace.h"
43 #include "catalog/pg_opclass.h"
44 #include "catalog/pg_tablespace.h"
45 #include "catalog/pg_trigger.h"
46 #include "catalog/pg_type.h"
47 #include "catalog/pg_type_fn.h"
48 #include "catalog/storage.h"
49 #include "catalog/storage_xlog.h"
50 #include "catalog/toasting.h"
51 #include "commands/cluster.h"
52 #include "commands/comment.h"
53 #include "commands/defrem.h"
54 #include "commands/event_trigger.h"
55 #include "commands/policy.h"
56 #include "commands/sequence.h"
57 #include "commands/tablecmds.h"
58 #include "commands/tablespace.h"
59 #include "commands/trigger.h"
60 #include "commands/typecmds.h"
61 #include "commands/user.h"
62 #include "executor/executor.h"
63 #include "foreign/foreign.h"
64 #include "miscadmin.h"
65 #include "nodes/makefuncs.h"
66 #include "nodes/nodeFuncs.h"
67 #include "nodes/parsenodes.h"
68 #include "optimizer/clauses.h"
69 #include "optimizer/planner.h"
70 #include "optimizer/predtest.h"
71 #include "optimizer/prep.h"
72 #include "optimizer/var.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"
82 #include "pgstat.h"
83 #include "rewrite/rewriteDefine.h"
84 #include "rewrite/rewriteHandler.h"
85 #include "rewrite/rewriteManip.h"
86 #include "storage/bufmgr.h"
87 #include "storage/lmgr.h"
88 #include "storage/lock.h"
89 #include "storage/predicate.h"
90 #include "storage/smgr.h"
91 #include "utils/acl.h"
92 #include "utils/builtins.h"
93 #include "utils/fmgroids.h"
94 #include "utils/inval.h"
95 #include "utils/lsyscache.h"
96 #include "utils/memutils.h"
97 #include "utils/relcache.h"
98 #include "utils/ruleutils.h"
99 #include "utils/snapmgr.h"
100 #include "utils/syscache.h"
101 #include "utils/tqual.h"
102 #include "utils/typcache.h"
103
104
105 /*
106  * ON COMMIT action list
107  */
108 typedef struct OnCommitItem
109 {
110         Oid                     relid;                  /* relid of relation */
111         OnCommitAction oncommit;        /* what to do at end of xact */
112
113         /*
114          * If this entry was created during the current transaction,
115          * creating_subid is the ID of the creating subxact; if created in a prior
116          * transaction, creating_subid is zero.  If deleted during the current
117          * transaction, deleting_subid is the ID of the deleting subxact; if no
118          * deletion request is pending, deleting_subid is zero.
119          */
120         SubTransactionId creating_subid;
121         SubTransactionId deleting_subid;
122 } OnCommitItem;
123
124 static List *on_commits = NIL;
125
126
127 /*
128  * State information for ALTER TABLE
129  *
130  * The pending-work queue for an ALTER TABLE is a List of AlteredTableInfo
131  * structs, one for each table modified by the operation (the named table
132  * plus any child tables that are affected).  We save lists of subcommands
133  * to apply to this table (possibly modified by parse transformation steps);
134  * these lists will be executed in Phase 2.  If a Phase 3 step is needed,
135  * necessary information is stored in the constraints and newvals lists.
136  *
137  * Phase 2 is divided into multiple passes; subcommands are executed in
138  * a pass determined by subcommand type.
139  */
140
141 #define AT_PASS_UNSET                   -1              /* UNSET will cause ERROR */
142 #define AT_PASS_DROP                    0               /* DROP (all flavors) */
143 #define AT_PASS_ALTER_TYPE              1               /* ALTER COLUMN TYPE */
144 #define AT_PASS_OLD_INDEX               2               /* re-add existing indexes */
145 #define AT_PASS_OLD_CONSTR              3               /* re-add existing constraints */
146 #define AT_PASS_COL_ATTRS               4               /* set other column attributes */
147 /* We could support a RENAME COLUMN pass here, but not currently used */
148 #define AT_PASS_ADD_COL                 5               /* ADD COLUMN */
149 #define AT_PASS_ADD_INDEX               6               /* ADD indexes */
150 #define AT_PASS_ADD_CONSTR              7               /* ADD constraints, defaults */
151 #define AT_PASS_MISC                    8               /* other stuff */
152 #define AT_NUM_PASSES                   9
153
154 typedef struct AlteredTableInfo
155 {
156         /* Information saved before any work commences: */
157         Oid                     relid;                  /* Relation to work on */
158         char            relkind;                /* Its relkind */
159         TupleDesc       oldDesc;                /* Pre-modification tuple descriptor */
160         /* Information saved by Phase 1 for Phase 2: */
161         List       *subcmds[AT_NUM_PASSES]; /* Lists of AlterTableCmd */
162         /* Information saved by Phases 1/2 for Phase 3: */
163         List       *constraints;        /* List of NewConstraint */
164         List       *newvals;            /* List of NewColumnValue */
165         bool            new_notnull;    /* T if we added new NOT NULL constraints */
166         int                     rewrite;                /* Reason for forced rewrite, if any */
167         Oid                     newTableSpace;  /* new tablespace; 0 means no change */
168         bool            chgPersistence; /* T if SET LOGGED/UNLOGGED is used */
169         char            newrelpersistence;              /* if above is true */
170         List       *partition_constraint;       /* for attach partition validation */
171         /* Objects to rebuild after completing ALTER TYPE operations */
172         List       *changedConstraintOids;      /* OIDs of constraints to rebuild */
173         List       *changedConstraintDefs;      /* string definitions of same */
174         List       *changedIndexOids;           /* OIDs of indexes to rebuild */
175         List       *changedIndexDefs;           /* string definitions of same */
176 } AlteredTableInfo;
177
178 /* Struct describing one new constraint to check in Phase 3 scan */
179 /* Note: new NOT NULL constraints are handled elsewhere */
180 typedef struct NewConstraint
181 {
182         char       *name;                       /* Constraint name, or NULL if none */
183         ConstrType      contype;                /* CHECK or FOREIGN */
184         Oid                     refrelid;               /* PK rel, if FOREIGN */
185         Oid                     refindid;               /* OID of PK's index, if FOREIGN */
186         Oid                     conid;                  /* OID of pg_constraint entry, if FOREIGN */
187         Node       *qual;                       /* Check expr or CONSTR_FOREIGN Constraint */
188         List       *qualstate;          /* Execution state for CHECK */
189 } NewConstraint;
190
191 /*
192  * Struct describing one new column value that needs to be computed during
193  * Phase 3 copy (this could be either a new column with a non-null default, or
194  * a column that we're changing the type of).  Columns without such an entry
195  * are just copied from the old table during ATRewriteTable.  Note that the
196  * expr is an expression over *old* table values.
197  */
198 typedef struct NewColumnValue
199 {
200         AttrNumber      attnum;                 /* which column */
201         Expr       *expr;                       /* expression to compute */
202         ExprState  *exprstate;          /* execution state */
203 } NewColumnValue;
204
205 /*
206  * Error-reporting support for RemoveRelations
207  */
208 struct dropmsgstrings
209 {
210         char            kind;
211         int                     nonexistent_code;
212         const char *nonexistent_msg;
213         const char *skipping_msg;
214         const char *nota_msg;
215         const char *drophint_msg;
216 };
217
218 static const struct dropmsgstrings dropmsgstringarray[] = {
219         {RELKIND_RELATION,
220                 ERRCODE_UNDEFINED_TABLE,
221                 gettext_noop("table \"%s\" does not exist"),
222                 gettext_noop("table \"%s\" does not exist, skipping"),
223                 gettext_noop("\"%s\" is not a table"),
224         gettext_noop("Use DROP TABLE to remove a table.")},
225         {RELKIND_SEQUENCE,
226                 ERRCODE_UNDEFINED_TABLE,
227                 gettext_noop("sequence \"%s\" does not exist"),
228                 gettext_noop("sequence \"%s\" does not exist, skipping"),
229                 gettext_noop("\"%s\" is not a sequence"),
230         gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
231         {RELKIND_VIEW,
232                 ERRCODE_UNDEFINED_TABLE,
233                 gettext_noop("view \"%s\" does not exist"),
234                 gettext_noop("view \"%s\" does not exist, skipping"),
235                 gettext_noop("\"%s\" is not a view"),
236         gettext_noop("Use DROP VIEW to remove a view.")},
237         {RELKIND_MATVIEW,
238                 ERRCODE_UNDEFINED_TABLE,
239                 gettext_noop("materialized view \"%s\" does not exist"),
240                 gettext_noop("materialized view \"%s\" does not exist, skipping"),
241                 gettext_noop("\"%s\" is not a materialized view"),
242         gettext_noop("Use DROP MATERIALIZED VIEW to remove a materialized view.")},
243         {RELKIND_INDEX,
244                 ERRCODE_UNDEFINED_OBJECT,
245                 gettext_noop("index \"%s\" does not exist"),
246                 gettext_noop("index \"%s\" does not exist, skipping"),
247                 gettext_noop("\"%s\" is not an index"),
248         gettext_noop("Use DROP INDEX to remove an index.")},
249         {RELKIND_COMPOSITE_TYPE,
250                 ERRCODE_UNDEFINED_OBJECT,
251                 gettext_noop("type \"%s\" does not exist"),
252                 gettext_noop("type \"%s\" does not exist, skipping"),
253                 gettext_noop("\"%s\" is not a type"),
254         gettext_noop("Use DROP TYPE to remove a type.")},
255         {RELKIND_FOREIGN_TABLE,
256                 ERRCODE_UNDEFINED_OBJECT,
257                 gettext_noop("foreign table \"%s\" does not exist"),
258                 gettext_noop("foreign table \"%s\" does not exist, skipping"),
259                 gettext_noop("\"%s\" is not a foreign table"),
260         gettext_noop("Use DROP FOREIGN TABLE to remove a foreign table.")},
261         {RELKIND_PARTITIONED_TABLE,
262                 ERRCODE_UNDEFINED_TABLE,
263                 gettext_noop("table \"%s\" does not exist"),
264                 gettext_noop("table \"%s\" does not exist, skipping"),
265                 gettext_noop("\"%s\" is not a table"),
266         gettext_noop("Use DROP TABLE to remove a table.")},
267         {'\0', 0, NULL, NULL, NULL, NULL}
268 };
269
270 struct DropRelationCallbackState
271 {
272         char            relkind;
273         Oid                     heapOid;
274         bool            concurrent;
275 };
276
277 /* Alter table target-type flags for ATSimplePermissions */
278 #define         ATT_TABLE                               0x0001
279 #define         ATT_VIEW                                0x0002
280 #define         ATT_MATVIEW                             0x0004
281 #define         ATT_INDEX                               0x0008
282 #define         ATT_COMPOSITE_TYPE              0x0010
283 #define         ATT_FOREIGN_TABLE               0x0020
284
285 static void truncate_check_rel(Relation rel);
286 static List *MergeAttributes(List *schema, List *supers, char relpersistence,
287                                 bool is_partition, List **supOids, List **supconstr,
288                                 int *supOidCount);
289 static bool MergeCheckConstraint(List *constraints, char *name, Node *expr);
290 static void MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel);
291 static void MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel);
292 static void StoreCatalogInheritance(Oid relationId, List *supers,
293                                                 bool child_is_partition);
294 static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
295                                                  int16 seqNumber, Relation inhRelation,
296                                                  bool child_is_partition);
297 static int      findAttrByName(const char *attributeName, List *schema);
298 static void AlterIndexNamespaces(Relation classRel, Relation rel,
299                                    Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved);
300 static void AlterSeqNamespaces(Relation classRel, Relation rel,
301                                    Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved,
302                                    LOCKMODE lockmode);
303 static ObjectAddress ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
304                                           bool recurse, bool recursing, LOCKMODE lockmode);
305 static ObjectAddress ATExecValidateConstraint(Relation rel, char *constrName,
306                                                  bool recurse, bool recursing, LOCKMODE lockmode);
307 static int transformColumnNameList(Oid relId, List *colList,
308                                                 int16 *attnums, Oid *atttypids);
309 static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
310                                                    List **attnamelist,
311                                                    int16 *attnums, Oid *atttypids,
312                                                    Oid *opclasses);
313 static Oid transformFkeyCheckAttrs(Relation pkrel,
314                                                 int numattrs, int16 *attnums,
315                                                 Oid *opclasses);
316 static void checkFkeyPermissions(Relation rel, int16 *attnums, int natts);
317 static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
318                          Oid *funcid);
319 static void validateCheckConstraint(Relation rel, HeapTuple constrtup);
320 static void validateForeignKeyConstraint(char *conname,
321                                                          Relation rel, Relation pkrel,
322                                                          Oid pkindOid, Oid constraintOid);
323 static void createForeignKeyTriggers(Relation rel, Oid refRelOid,
324                                                  Constraint *fkconstraint,
325                                                  Oid constraintOid, Oid indexOid);
326 static void ATController(AlterTableStmt *parsetree,
327                          Relation rel, List *cmds, bool recurse, LOCKMODE lockmode);
328 static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
329                   bool recurse, bool recursing, LOCKMODE lockmode);
330 static void ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode);
331 static void ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
332                   AlterTableCmd *cmd, LOCKMODE lockmode);
333 static void ATRewriteTables(AlterTableStmt *parsetree,
334                                 List **wqueue, LOCKMODE lockmode);
335 static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode);
336 static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);
337 static void ATSimplePermissions(Relation rel, int allowed_targets);
338 static void ATWrongRelkindError(Relation rel, int allowed_targets);
339 static void ATSimpleRecursion(List **wqueue, Relation rel,
340                                   AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode);
341 static void ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
342                                           LOCKMODE lockmode);
343 static List *find_typed_table_dependencies(Oid typeOid, const char *typeName,
344                                                           DropBehavior behavior);
345 static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
346                                 bool is_view, AlterTableCmd *cmd, LOCKMODE lockmode);
347 static ObjectAddress ATExecAddColumn(List **wqueue, AlteredTableInfo *tab,
348                                 Relation rel, ColumnDef *colDef, bool isOid,
349                                 bool recurse, bool recursing,
350                                 bool if_not_exists, LOCKMODE lockmode);
351 static bool check_for_column_name_collision(Relation rel, const char *colname,
352                                                                 bool if_not_exists);
353 static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid);
354 static void add_column_collation_dependency(Oid relid, int32 attnum, Oid collid);
355 static void ATPrepAddOids(List **wqueue, Relation rel, bool recurse,
356                           AlterTableCmd *cmd, LOCKMODE lockmode);
357 static void ATPrepDropNotNull(Relation rel, bool recurse, bool recursing);
358 static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode);
359 static void ATPrepSetNotNull(Relation rel, bool recurse, bool recursing);
360 static ObjectAddress ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
361                                  const char *colName, LOCKMODE lockmode);
362 static ObjectAddress ATExecColumnDefault(Relation rel, const char *colName,
363                                         Node *newDefault, LOCKMODE lockmode);
364 static void ATPrepSetStatistics(Relation rel, const char *colName,
365                                         Node *newValue, LOCKMODE lockmode);
366 static ObjectAddress ATExecSetStatistics(Relation rel, const char *colName,
367                                         Node *newValue, LOCKMODE lockmode);
368 static ObjectAddress ATExecSetOptions(Relation rel, const char *colName,
369                                  Node *options, bool isReset, LOCKMODE lockmode);
370 static ObjectAddress ATExecSetStorage(Relation rel, const char *colName,
371                                  Node *newValue, LOCKMODE lockmode);
372 static void ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
373                                  AlterTableCmd *cmd, LOCKMODE lockmode);
374 static ObjectAddress ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
375                                  DropBehavior behavior,
376                                  bool recurse, bool recursing,
377                                  bool missing_ok, LOCKMODE lockmode);
378 static ObjectAddress ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
379                            IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode);
380 static ObjectAddress ATExecAddConstraint(List **wqueue,
381                                         AlteredTableInfo *tab, Relation rel,
382                                         Constraint *newConstraint, bool recurse, bool is_readd,
383                                         LOCKMODE lockmode);
384 static ObjectAddress ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
385                                                  IndexStmt *stmt, LOCKMODE lockmode);
386 static ObjectAddress ATAddCheckConstraint(List **wqueue,
387                                          AlteredTableInfo *tab, Relation rel,
388                                          Constraint *constr,
389                                          bool recurse, bool recursing, bool is_readd,
390                                          LOCKMODE lockmode);
391 static ObjectAddress ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
392                                                   Constraint *fkconstraint, LOCKMODE lockmode);
393 static void ATExecDropConstraint(Relation rel, const char *constrName,
394                                          DropBehavior behavior,
395                                          bool recurse, bool recursing,
396                                          bool missing_ok, LOCKMODE lockmode);
397 static void ATPrepAlterColumnType(List **wqueue,
398                                           AlteredTableInfo *tab, Relation rel,
399                                           bool recurse, bool recursing,
400                                           AlterTableCmd *cmd, LOCKMODE lockmode);
401 static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno);
402 static ObjectAddress ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
403                                           AlterTableCmd *cmd, LOCKMODE lockmode);
404 static ObjectAddress ATExecAlterColumnGenericOptions(Relation rel, const char *colName,
405                                                                 List *options, LOCKMODE lockmode);
406 static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab,
407                                            LOCKMODE lockmode);
408 static void ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId,
409                                          char *cmd, List **wqueue, LOCKMODE lockmode,
410                                          bool rewrite);
411 static void RebuildConstraintComment(AlteredTableInfo *tab, int pass,
412                                                  Oid objid, Relation rel, char *conname);
413 static void TryReuseIndex(Oid oldId, IndexStmt *stmt);
414 static void TryReuseForeignKey(Oid oldId, Constraint *con);
415 static void change_owner_fix_column_acls(Oid relationOid,
416                                                          Oid oldOwnerId, Oid newOwnerId);
417 static void change_owner_recurse_to_sequences(Oid relationOid,
418                                                                   Oid newOwnerId, LOCKMODE lockmode);
419 static ObjectAddress ATExecClusterOn(Relation rel, const char *indexName,
420                                 LOCKMODE lockmode);
421 static void ATExecDropCluster(Relation rel, LOCKMODE lockmode);
422 static bool ATPrepChangePersistence(Relation rel, bool toLogged);
423 static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
424                                         char *tablespacename, LOCKMODE lockmode);
425 static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode);
426 static void ATExecSetRelOptions(Relation rel, List *defList,
427                                         AlterTableType operation,
428                                         LOCKMODE lockmode);
429 static void ATExecEnableDisableTrigger(Relation rel, char *trigname,
430                                            char fires_when, bool skip_system, LOCKMODE lockmode);
431 static void ATExecEnableDisableRule(Relation rel, char *rulename,
432                                                 char fires_when, LOCKMODE lockmode);
433 static void ATPrepAddInherit(Relation child_rel);
434 static ObjectAddress ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode);
435 static ObjectAddress ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode);
436 static void drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid);
437 static ObjectAddress ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode);
438 static void ATExecDropOf(Relation rel, LOCKMODE lockmode);
439 static void ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode);
440 static void ATExecGenericOptions(Relation rel, List *options);
441 static void ATExecEnableRowSecurity(Relation rel);
442 static void ATExecDisableRowSecurity(Relation rel);
443 static void ATExecForceNoForceRowSecurity(Relation rel, bool force_rls);
444
445 static void copy_relation_data(SMgrRelation rel, SMgrRelation dst,
446                                    ForkNumber forkNum, char relpersistence);
447 static const char *storage_name(char c);
448
449 static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid,
450                                                                 Oid oldRelOid, void *arg);
451 static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
452                                                                  Oid oldrelid, void *arg);
453 static bool is_partition_attr(Relation rel, AttrNumber attnum, bool *used_in_expr);
454 static PartitionSpec *transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy);
455 static void ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
456                                           List **partexprs, Oid *partopclass, Oid *partcollation);
457 static void CreateInheritance(Relation child_rel, Relation parent_rel);
458 static void RemoveInheritance(Relation child_rel, Relation parent_rel);
459 static ObjectAddress ATExecAttachPartition(List **wqueue, Relation rel,
460                                           PartitionCmd *cmd);
461 static ObjectAddress ATExecDetachPartition(Relation rel, RangeVar *name);
462
463
464 /* ----------------------------------------------------------------
465  *              DefineRelation
466  *                              Creates a new relation.
467  *
468  * stmt carries parsetree information from an ordinary CREATE TABLE statement.
469  * The other arguments are used to extend the behavior for other cases:
470  * relkind: relkind to assign to the new relation
471  * ownerId: if not InvalidOid, use this as the new relation's owner.
472  * typaddress: if not null, it's set to the pg_type entry's address.
473  *
474  * Note that permissions checks are done against current user regardless of
475  * ownerId.  A nonzero ownerId is used when someone is creating a relation
476  * "on behalf of" someone else, so we still want to see that the current user
477  * has permissions to do it.
478  *
479  * If successful, returns the address of the new relation.
480  * ----------------------------------------------------------------
481  */
482 ObjectAddress
483 DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
484                            ObjectAddress *typaddress, const char *queryString)
485 {
486         char            relname[NAMEDATALEN];
487         Oid                     namespaceId;
488         List       *schema = stmt->tableElts;
489         Oid                     relationId;
490         Oid                     tablespaceId;
491         Relation        rel;
492         TupleDesc       descriptor;
493         List       *inheritOids;
494         List       *old_constraints;
495         bool            localHasOids;
496         int                     parentOidCount;
497         List       *rawDefaults;
498         List       *cookedDefaults;
499         Datum           reloptions;
500         ListCell   *listptr;
501         AttrNumber      attnum;
502         static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
503         Oid                     ofTypeId;
504         ObjectAddress address;
505
506         /*
507          * Truncate relname to appropriate length (probably a waste of time, as
508          * parser should have done this already).
509          */
510         StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);
511
512         /*
513          * Check consistency of arguments
514          */
515         if (stmt->oncommit != ONCOMMIT_NOOP
516                 && stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
517                 ereport(ERROR,
518                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
519                                  errmsg("ON COMMIT can only be used on temporary tables")));
520
521         if (stmt->partspec != NULL)
522         {
523                 if (relkind != RELKIND_RELATION)
524                         elog(ERROR, "unexpected relkind: %d", (int) relkind);
525
526                 relkind = RELKIND_PARTITIONED_TABLE;
527         }
528
529         /*
530          * Look up the namespace in which we are supposed to create the relation,
531          * check we have permission to create there, lock it against concurrent
532          * drop, and mark stmt->relation as RELPERSISTENCE_TEMP if a temporary
533          * namespace is selected.
534          */
535         namespaceId =
536                 RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock, NULL);
537
538         /*
539          * Security check: disallow creating temp tables from security-restricted
540          * code.  This is needed because calling code might not expect untrusted
541          * tables to appear in pg_temp at the front of its search path.
542          */
543         if (stmt->relation->relpersistence == RELPERSISTENCE_TEMP
544                 && InSecurityRestrictedOperation())
545                 ereport(ERROR,
546                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
547                                  errmsg("cannot create temporary table within security-restricted operation")));
548
549         /*
550          * Select tablespace to use.  If not specified, use default tablespace
551          * (which may in turn default to database's default).
552          */
553         if (stmt->tablespacename)
554         {
555                 tablespaceId = get_tablespace_oid(stmt->tablespacename, false);
556         }
557         else
558         {
559                 tablespaceId = GetDefaultTablespace(stmt->relation->relpersistence);
560                 /* note InvalidOid is OK in this case */
561         }
562
563         /* Check permissions except when using database's default */
564         if (OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
565         {
566                 AclResult       aclresult;
567
568                 aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),
569                                                                                    ACL_CREATE);
570                 if (aclresult != ACLCHECK_OK)
571                         aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
572                                                    get_tablespace_name(tablespaceId));
573         }
574
575         /* In all cases disallow placing user relations in pg_global */
576         if (tablespaceId == GLOBALTABLESPACE_OID)
577                 ereport(ERROR,
578                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
579                                  errmsg("only shared relations can be placed in pg_global tablespace")));
580
581         /* Identify user ID that will own the table */
582         if (!OidIsValid(ownerId))
583                 ownerId = GetUserId();
584
585         /*
586          * Parse and validate reloptions, if any.
587          */
588         reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
589                                                                          true, false);
590
591         if (relkind == RELKIND_VIEW)
592                 (void) view_reloptions(reloptions, true);
593         else
594                 (void) heap_reloptions(relkind, reloptions, true);
595
596         if (stmt->ofTypename)
597         {
598                 AclResult       aclresult;
599
600                 ofTypeId = typenameTypeId(NULL, stmt->ofTypename);
601
602                 aclresult = pg_type_aclcheck(ofTypeId, GetUserId(), ACL_USAGE);
603                 if (aclresult != ACLCHECK_OK)
604                         aclcheck_error_type(aclresult, ofTypeId);
605         }
606         else
607                 ofTypeId = InvalidOid;
608
609         /*
610          * Look up inheritance ancestors and generate relation schema, including
611          * inherited attributes.
612          */
613         schema = MergeAttributes(schema, stmt->inhRelations,
614                                                          stmt->relation->relpersistence,
615                                                          stmt->partbound != NULL,
616                                                          &inheritOids, &old_constraints, &parentOidCount);
617
618         /*
619          * Create a tuple descriptor from the relation schema.  Note that this
620          * deals with column names, types, and NOT NULL constraints, but not
621          * default values or CHECK constraints; we handle those below.
622          */
623         descriptor = BuildDescForRelation(schema);
624
625         /*
626          * Notice that we allow OIDs here only for plain tables and partitioned
627          * tables, even though some other relkinds can support them.  This is
628          * necessary because the default_with_oids GUC must apply only to plain
629          * tables and not any other relkind; doing otherwise would break existing
630          * pg_dump files.  We could allow explicit "WITH OIDS" while not allowing
631          * default_with_oids to affect other relkinds, but it would complicate
632          * interpretOidsOption().
633          */
634         localHasOids = interpretOidsOption(stmt->options,
635                                                                            (relkind == RELKIND_RELATION ||
636                                                                           relkind == RELKIND_PARTITIONED_TABLE));
637         descriptor->tdhasoid = (localHasOids || parentOidCount > 0);
638
639         /*
640          * If a partitioned table doesn't have the system OID column, then none
641          * of its partitions should have it.
642          */
643         if (stmt->partbound && parentOidCount == 0 && localHasOids)
644                 ereport(ERROR,
645                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
646                                  errmsg("cannot create table with OIDs as partition of table without OIDs")));
647
648         /*
649          * Find columns with default values and prepare for insertion of the
650          * defaults.  Pre-cooked (that is, inherited) defaults go into a list of
651          * CookedConstraint structs that we'll pass to heap_create_with_catalog,
652          * while raw defaults go into a list of RawColumnDefault structs that will
653          * be processed by AddRelationNewConstraints.  (We can't deal with raw
654          * expressions until we can do transformExpr.)
655          *
656          * We can set the atthasdef flags now in the tuple descriptor; this just
657          * saves StoreAttrDefault from having to do an immediate update of the
658          * pg_attribute rows.
659          */
660         rawDefaults = NIL;
661         cookedDefaults = NIL;
662         attnum = 0;
663
664         foreach(listptr, schema)
665         {
666                 ColumnDef  *colDef = lfirst(listptr);
667
668                 attnum++;
669
670                 if (colDef->raw_default != NULL)
671                 {
672                         RawColumnDefault *rawEnt;
673
674                         Assert(colDef->cooked_default == NULL);
675
676                         rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
677                         rawEnt->attnum = attnum;
678                         rawEnt->raw_default = colDef->raw_default;
679                         rawDefaults = lappend(rawDefaults, rawEnt);
680                         descriptor->attrs[attnum - 1]->atthasdef = true;
681                 }
682                 else if (colDef->cooked_default != NULL)
683                 {
684                         CookedConstraint *cooked;
685
686                         cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
687                         cooked->contype = CONSTR_DEFAULT;
688                         cooked->conoid = InvalidOid;            /* until created */
689                         cooked->name = NULL;
690                         cooked->attnum = attnum;
691                         cooked->expr = colDef->cooked_default;
692                         cooked->skip_validation = false;
693                         cooked->is_local = true;        /* not used for defaults */
694                         cooked->inhcount = 0;           /* ditto */
695                         cooked->is_no_inherit = false;
696                         cookedDefaults = lappend(cookedDefaults, cooked);
697                         descriptor->attrs[attnum - 1]->atthasdef = true;
698                 }
699         }
700
701         /*
702          * Create the relation.  Inherited defaults and constraints are passed in
703          * for immediate handling --- since they don't need parsing, they can be
704          * stored immediately.
705          */
706         relationId = heap_create_with_catalog(relname,
707                                                                                   namespaceId,
708                                                                                   tablespaceId,
709                                                                                   InvalidOid,
710                                                                                   InvalidOid,
711                                                                                   ofTypeId,
712                                                                                   ownerId,
713                                                                                   descriptor,
714                                                                                   list_concat(cookedDefaults,
715                                                                                                           old_constraints),
716                                                                                   relkind,
717                                                                                   stmt->relation->relpersistence,
718                                                                                   false,
719                                                                                   false,
720                                                                                   localHasOids,
721                                                                                   parentOidCount,
722                                                                                   stmt->oncommit,
723                                                                                   reloptions,
724                                                                                   true,
725                                                                                   allowSystemTableMods,
726                                                                                   false,
727                                                                                   typaddress);
728
729         /* Store inheritance information for new rel. */
730         StoreCatalogInheritance(relationId, inheritOids, stmt->partbound != NULL);
731
732         /*
733          * We must bump the command counter to make the newly-created relation
734          * tuple visible for opening.
735          */
736         CommandCounterIncrement();
737
738         /*
739          * Open the new relation and acquire exclusive lock on it.  This isn't
740          * really necessary for locking out other backends (since they can't see
741          * the new rel anyway until we commit), but it keeps the lock manager from
742          * complaining about deadlock risks.
743          */
744         rel = relation_open(relationId, AccessExclusiveLock);
745
746         /* Process and store partition bound, if any. */
747         if (stmt->partbound)
748         {
749                 Node       *bound;
750                 ParseState *pstate;
751                 Oid                     parentId = linitial_oid(inheritOids);
752                 Relation        parent;
753
754                 /* Already have strong enough lock on the parent */
755                 parent = heap_open(parentId, NoLock);
756
757                 /*
758                  * We are going to try to validate the partition bound specification
759                  * against the partition key of parentRel, so it better have one.
760                  */
761                 if (parent->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
762                         ereport(ERROR,
763                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
764                                          errmsg("\"%s\" is not partitioned",
765                                                         RelationGetRelationName(parent))));
766
767                 /* Tranform the bound values */
768                 pstate = make_parsestate(NULL);
769                 pstate->p_sourcetext = queryString;
770                 bound = transformPartitionBound(pstate, parent, stmt->partbound);
771
772                 /*
773                  * Check first that the new partition's bound is valid and does not
774                  * overlap with any of existing partitions of the parent - note that
775                  * it does not return on error.
776                  */
777                 check_new_partition_bound(relname, parent, bound);
778
779                 /* Update the pg_class entry. */
780                 StorePartitionBound(rel, parent, bound);
781
782                 heap_close(parent, NoLock);
783
784                 /*
785                  * The code that follows may also update the pg_class tuple to update
786                  * relnumchecks, so bump up the command counter to avoid the "already
787                  * updated by self" error.
788                  */
789                 CommandCounterIncrement();
790         }
791
792         /*
793          * Process the partitioning specification (if any) and store the partition
794          * key information into the catalog.
795          */
796         if (stmt->partspec)
797         {
798                 char            strategy;
799                 int                     partnatts,
800                                         i;
801                 AttrNumber      partattrs[PARTITION_MAX_KEYS];
802                 Oid                     partopclass[PARTITION_MAX_KEYS];
803                 Oid                     partcollation[PARTITION_MAX_KEYS];
804                 List       *partexprs = NIL;
805                 List       *cmds = NIL;
806
807                 /*
808                  * We need to transform the raw parsetrees corresponding to partition
809                  * expressions into executable expression trees.  Like column defaults
810                  * and CHECK constraints, we could not have done the transformation
811                  * earlier.
812                  */
813                 stmt->partspec = transformPartitionSpec(rel, stmt->partspec,
814                                                                                                 &strategy);
815                 ComputePartitionAttrs(rel, stmt->partspec->partParams,
816                                                           partattrs, &partexprs, partopclass,
817                                                           partcollation);
818
819                 partnatts = list_length(stmt->partspec->partParams);
820                 StorePartitionKey(rel, strategy, partnatts, partattrs, partexprs,
821                                                   partopclass, partcollation);
822
823                 /* Force key columns to be NOT NULL when using range partitioning */
824                 if (strategy == PARTITION_STRATEGY_RANGE)
825                 {
826                         for (i = 0; i < partnatts; i++)
827                         {
828                                 AttrNumber      partattno = partattrs[i];
829                                 Form_pg_attribute attform = descriptor->attrs[partattno - 1];
830
831                                 if (partattno != 0 && !attform->attnotnull)
832                                 {
833                                         /* Add a subcommand to make this one NOT NULL */
834                                         AlterTableCmd *cmd = makeNode(AlterTableCmd);
835
836                                         cmd->subtype = AT_SetNotNull;
837                                         cmd->name = pstrdup(NameStr(attform->attname));
838                                         cmds = lappend(cmds, cmd);
839                                 }
840                         }
841
842                         /*
843                          * Although, there cannot be any partitions yet, we still need to
844                          * pass true for recurse; ATPrepSetNotNull() complains if we don't
845                          */
846                         if (cmds != NIL)
847                                 AlterTableInternal(RelationGetRelid(rel), cmds, true);
848                 }
849         }
850
851         /*
852          * Now add any newly specified column default values and CHECK constraints
853          * to the new relation.  These are passed to us in the form of raw
854          * parsetrees; we need to transform them to executable expression trees
855          * before they can be added. The most convenient way to do that is to
856          * apply the parser's transformExpr routine, but transformExpr doesn't
857          * work unless we have a pre-existing relation. So, the transformation has
858          * to be postponed to this final step of CREATE TABLE.
859          */
860         if (rawDefaults || stmt->constraints)
861                 AddRelationNewConstraints(rel, rawDefaults, stmt->constraints,
862                                                                   true, true, false);
863
864         ObjectAddressSet(address, RelationRelationId, relationId);
865
866         /*
867          * Clean up.  We keep lock on new relation (although it shouldn't be
868          * visible to anyone else anyway, until commit).
869          */
870         relation_close(rel, NoLock);
871
872         return address;
873 }
874
875 /*
876  * Emit the right error or warning message for a "DROP" command issued on a
877  * non-existent relation
878  */
879 static void
880 DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
881 {
882         const struct dropmsgstrings *rentry;
883
884         if (rel->schemaname != NULL &&
885                 !OidIsValid(LookupNamespaceNoError(rel->schemaname)))
886         {
887                 if (!missing_ok)
888                 {
889                         ereport(ERROR,
890                                         (errcode(ERRCODE_UNDEFINED_SCHEMA),
891                                    errmsg("schema \"%s\" does not exist", rel->schemaname)));
892                 }
893                 else
894                 {
895                         ereport(NOTICE,
896                                         (errmsg("schema \"%s\" does not exist, skipping",
897                                                         rel->schemaname)));
898                 }
899                 return;
900         }
901
902         for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
903         {
904                 if (rentry->kind == rightkind)
905                 {
906                         if (!missing_ok)
907                         {
908                                 ereport(ERROR,
909                                                 (errcode(rentry->nonexistent_code),
910                                                  errmsg(rentry->nonexistent_msg, rel->relname)));
911                         }
912                         else
913                         {
914                                 ereport(NOTICE, (errmsg(rentry->skipping_msg, rel->relname)));
915                                 break;
916                         }
917                 }
918         }
919
920         Assert(rentry->kind != '\0');           /* Should be impossible */
921 }
922
923 /*
924  * Emit the right error message for a "DROP" command issued on a
925  * relation of the wrong type
926  */
927 static void
928 DropErrorMsgWrongType(const char *relname, char wrongkind, char rightkind)
929 {
930         const struct dropmsgstrings *rentry;
931         const struct dropmsgstrings *wentry;
932
933         for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
934                 if (rentry->kind == rightkind)
935                         break;
936         Assert(rentry->kind != '\0');
937
938         for (wentry = dropmsgstringarray; wentry->kind != '\0'; wentry++)
939                 if (wentry->kind == wrongkind)
940                         break;
941         /* wrongkind could be something we don't have in our table... */
942
943         ereport(ERROR,
944                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
945                          errmsg(rentry->nota_msg, relname),
946            (wentry->kind != '\0') ? errhint("%s", _(wentry->drophint_msg)) : 0));
947 }
948
949 /*
950  * RemoveRelations
951  *              Implements DROP TABLE, DROP INDEX, DROP SEQUENCE, DROP VIEW,
952  *              DROP MATERIALIZED VIEW, DROP FOREIGN TABLE
953  */
954 void
955 RemoveRelations(DropStmt *drop)
956 {
957         ObjectAddresses *objects;
958         char            relkind;
959         ListCell   *cell;
960         int                     flags = 0;
961         LOCKMODE        lockmode = AccessExclusiveLock;
962
963         /* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */
964         if (drop->concurrent)
965         {
966                 flags |= PERFORM_DELETION_CONCURRENTLY;
967                 lockmode = ShareUpdateExclusiveLock;
968                 Assert(drop->removeType == OBJECT_INDEX);
969                 if (list_length(drop->objects) != 1)
970                         ereport(ERROR,
971                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
972                                          errmsg("DROP INDEX CONCURRENTLY does not support dropping multiple objects")));
973                 if (drop->behavior == DROP_CASCADE)
974                         ereport(ERROR,
975                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
976                                 errmsg("DROP INDEX CONCURRENTLY does not support CASCADE")));
977         }
978
979         /*
980          * First we identify all the relations, then we delete them in a single
981          * performMultipleDeletions() call.  This is to avoid unwanted DROP
982          * RESTRICT errors if one of the relations depends on another.
983          */
984
985         /* Determine required relkind */
986         switch (drop->removeType)
987         {
988                 case OBJECT_TABLE:
989                         relkind = RELKIND_RELATION;
990                         break;
991
992                 case OBJECT_INDEX:
993                         relkind = RELKIND_INDEX;
994                         break;
995
996                 case OBJECT_SEQUENCE:
997                         relkind = RELKIND_SEQUENCE;
998                         break;
999
1000                 case OBJECT_VIEW:
1001                         relkind = RELKIND_VIEW;
1002                         break;
1003
1004                 case OBJECT_MATVIEW:
1005                         relkind = RELKIND_MATVIEW;
1006                         break;
1007
1008                 case OBJECT_FOREIGN_TABLE:
1009                         relkind = RELKIND_FOREIGN_TABLE;
1010                         break;
1011
1012                 default:
1013                         elog(ERROR, "unrecognized drop object type: %d",
1014                                  (int) drop->removeType);
1015                         relkind = 0;            /* keep compiler quiet */
1016                         break;
1017         }
1018
1019         /* Lock and validate each relation; build a list of object addresses */
1020         objects = new_object_addresses();
1021
1022         foreach(cell, drop->objects)
1023         {
1024                 RangeVar   *rel = makeRangeVarFromNameList((List *) lfirst(cell));
1025                 Oid                     relOid;
1026                 ObjectAddress obj;
1027                 struct DropRelationCallbackState state;
1028
1029                 /*
1030                  * These next few steps are a great deal like relation_openrv, but we
1031                  * don't bother building a relcache entry since we don't need it.
1032                  *
1033                  * Check for shared-cache-inval messages before trying to access the
1034                  * relation.  This is needed to cover the case where the name
1035                  * identifies a rel that has been dropped and recreated since the
1036                  * start of our transaction: if we don't flush the old syscache entry,
1037                  * then we'll latch onto that entry and suffer an error later.
1038                  */
1039                 AcceptInvalidationMessages();
1040
1041                 /* Look up the appropriate relation using namespace search. */
1042                 state.relkind = relkind;
1043                 state.heapOid = InvalidOid;
1044                 state.concurrent = drop->concurrent;
1045                 relOid = RangeVarGetRelidExtended(rel, lockmode, true,
1046                                                                                   false,
1047                                                                                   RangeVarCallbackForDropRelation,
1048                                                                                   (void *) &state);
1049
1050                 /* Not there? */
1051                 if (!OidIsValid(relOid))
1052                 {
1053                         DropErrorMsgNonExistent(rel, relkind, drop->missing_ok);
1054                         continue;
1055                 }
1056
1057                 /* OK, we're ready to delete this one */
1058                 obj.classId = RelationRelationId;
1059                 obj.objectId = relOid;
1060                 obj.objectSubId = 0;
1061
1062                 add_exact_object_address(&obj, objects);
1063         }
1064
1065         performMultipleDeletions(objects, drop->behavior, flags);
1066
1067         free_object_addresses(objects);
1068 }
1069
1070 /*
1071  * Before acquiring a table lock, check whether we have sufficient rights.
1072  * In the case of DROP INDEX, also try to lock the table before the index.
1073  */
1074 static void
1075 RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
1076                                                                 void *arg)
1077 {
1078         HeapTuple       tuple;
1079         struct DropRelationCallbackState *state;
1080         char            relkind;
1081         char            expected_relkind;
1082         Form_pg_class classform;
1083         LOCKMODE        heap_lockmode;
1084
1085         state = (struct DropRelationCallbackState *) arg;
1086         relkind = state->relkind;
1087         heap_lockmode = state->concurrent ?
1088                 ShareUpdateExclusiveLock : AccessExclusiveLock;
1089
1090         /*
1091          * If we previously locked some other index's heap, and the name we're
1092          * looking up no longer refers to that relation, release the now-useless
1093          * lock.
1094          */
1095         if (relOid != oldRelOid && OidIsValid(state->heapOid))
1096         {
1097                 UnlockRelationOid(state->heapOid, heap_lockmode);
1098                 state->heapOid = InvalidOid;
1099         }
1100
1101         /* Didn't find a relation, so no need for locking or permission checks. */
1102         if (!OidIsValid(relOid))
1103                 return;
1104
1105         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
1106         if (!HeapTupleIsValid(tuple))
1107                 return;                                 /* concurrently dropped, so nothing to do */
1108         classform = (Form_pg_class) GETSTRUCT(tuple);
1109
1110         /*
1111          * Both RELKIND_RELATION and RELKIND_PARTITIONED_TABLE are OBJECT_TABLE,
1112          * but RemoveRelations() can only pass one relkind for a given relation.
1113          * It chooses RELKIND_RELATION for both regular and partitioned tables.
1114          * That means we must be careful before giving the wrong type error when
1115          * the relation is RELKIND_PARTITIONED_TABLE.
1116          */
1117         if (classform->relkind == RELKIND_PARTITIONED_TABLE)
1118                 expected_relkind = RELKIND_RELATION;
1119         else
1120                 expected_relkind = classform->relkind;
1121
1122         if (relkind != expected_relkind)
1123                 DropErrorMsgWrongType(rel->relname, classform->relkind, relkind);
1124
1125         /* Allow DROP to either table owner or schema owner */
1126         if (!pg_class_ownercheck(relOid, GetUserId()) &&
1127                 !pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
1128                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
1129                                            rel->relname);
1130
1131         if (!allowSystemTableMods && IsSystemClass(relOid, classform))
1132                 ereport(ERROR,
1133                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1134                                  errmsg("permission denied: \"%s\" is a system catalog",
1135                                                 rel->relname)));
1136
1137         ReleaseSysCache(tuple);
1138
1139         /*
1140          * In DROP INDEX, attempt to acquire lock on the parent table before
1141          * locking the index.  index_drop() will need this anyway, and since
1142          * regular queries lock tables before their indexes, we risk deadlock if
1143          * we do it the other way around.  No error if we don't find a pg_index
1144          * entry, though --- the relation may have been dropped.
1145          */
1146         if (relkind == RELKIND_INDEX && relOid != oldRelOid)
1147         {
1148                 state->heapOid = IndexGetRelation(relOid, true);
1149                 if (OidIsValid(state->heapOid))
1150                         LockRelationOid(state->heapOid, heap_lockmode);
1151         }
1152 }
1153
1154 /*
1155  * ExecuteTruncate
1156  *              Executes a TRUNCATE command.
1157  *
1158  * This is a multi-relation truncate.  We first open and grab exclusive
1159  * lock on all relations involved, checking permissions and otherwise
1160  * verifying that the relation is OK for truncation.  In CASCADE mode,
1161  * relations having FK references to the targeted relations are automatically
1162  * added to the group; in RESTRICT mode, we check that all FK references are
1163  * internal to the group that's being truncated.  Finally all the relations
1164  * are truncated and reindexed.
1165  */
1166 void
1167 ExecuteTruncate(TruncateStmt *stmt)
1168 {
1169         List       *rels = NIL;
1170         List       *relids = NIL;
1171         List       *seq_relids = NIL;
1172         EState     *estate;
1173         ResultRelInfo *resultRelInfos;
1174         ResultRelInfo *resultRelInfo;
1175         SubTransactionId mySubid;
1176         ListCell   *cell;
1177
1178         /*
1179          * Open, exclusive-lock, and check all the explicitly-specified relations
1180          */
1181         foreach(cell, stmt->relations)
1182         {
1183                 RangeVar   *rv = lfirst(cell);
1184                 Relation        rel;
1185                 bool            recurse = rv->inh;
1186                 Oid                     myrelid;
1187
1188                 rel = heap_openrv(rv, AccessExclusiveLock);
1189                 myrelid = RelationGetRelid(rel);
1190                 /* don't throw error for "TRUNCATE foo, foo" */
1191                 if (list_member_oid(relids, myrelid))
1192                 {
1193                         heap_close(rel, AccessExclusiveLock);
1194                         continue;
1195                 }
1196                 truncate_check_rel(rel);
1197                 rels = lappend(rels, rel);
1198                 relids = lappend_oid(relids, myrelid);
1199
1200                 if (recurse)
1201                 {
1202                         ListCell   *child;
1203                         List       *children;
1204
1205                         children = find_all_inheritors(myrelid, AccessExclusiveLock, NULL);
1206
1207                         foreach(child, children)
1208                         {
1209                                 Oid                     childrelid = lfirst_oid(child);
1210
1211                                 if (list_member_oid(relids, childrelid))
1212                                         continue;
1213
1214                                 /* find_all_inheritors already got lock */
1215                                 rel = heap_open(childrelid, NoLock);
1216                                 truncate_check_rel(rel);
1217                                 rels = lappend(rels, rel);
1218                                 relids = lappend_oid(relids, childrelid);
1219                         }
1220                 }
1221                 else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1222                         ereport(ERROR,
1223                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1224                                          errmsg("must truncate child tables too")));
1225         }
1226
1227         /*
1228          * In CASCADE mode, suck in all referencing relations as well.  This
1229          * requires multiple iterations to find indirectly-dependent relations. At
1230          * each phase, we need to exclusive-lock new rels before looking for their
1231          * dependencies, else we might miss something.  Also, we check each rel as
1232          * soon as we open it, to avoid a faux pas such as holding lock for a long
1233          * time on a rel we have no permissions for.
1234          */
1235         if (stmt->behavior == DROP_CASCADE)
1236         {
1237                 for (;;)
1238                 {
1239                         List       *newrelids;
1240
1241                         newrelids = heap_truncate_find_FKs(relids);
1242                         if (newrelids == NIL)
1243                                 break;                  /* nothing else to add */
1244
1245                         foreach(cell, newrelids)
1246                         {
1247                                 Oid                     relid = lfirst_oid(cell);
1248                                 Relation        rel;
1249
1250                                 rel = heap_open(relid, AccessExclusiveLock);
1251                                 ereport(NOTICE,
1252                                                 (errmsg("truncate cascades to table \"%s\"",
1253                                                                 RelationGetRelationName(rel))));
1254                                 truncate_check_rel(rel);
1255                                 rels = lappend(rels, rel);
1256                                 relids = lappend_oid(relids, relid);
1257                         }
1258                 }
1259         }
1260
1261         /*
1262          * Check foreign key references.  In CASCADE mode, this should be
1263          * unnecessary since we just pulled in all the references; but as a
1264          * cross-check, do it anyway if in an Assert-enabled build.
1265          */
1266 #ifdef USE_ASSERT_CHECKING
1267         heap_truncate_check_FKs(rels, false);
1268 #else
1269         if (stmt->behavior == DROP_RESTRICT)
1270                 heap_truncate_check_FKs(rels, false);
1271 #endif
1272
1273         /*
1274          * If we are asked to restart sequences, find all the sequences, lock them
1275          * (we need AccessExclusiveLock for ResetSequence), and check permissions.
1276          * We want to do this early since it's pointless to do all the truncation
1277          * work only to fail on sequence permissions.
1278          */
1279         if (stmt->restart_seqs)
1280         {
1281                 foreach(cell, rels)
1282                 {
1283                         Relation        rel = (Relation) lfirst(cell);
1284                         List       *seqlist = getOwnedSequences(RelationGetRelid(rel));
1285                         ListCell   *seqcell;
1286
1287                         foreach(seqcell, seqlist)
1288                         {
1289                                 Oid                     seq_relid = lfirst_oid(seqcell);
1290                                 Relation        seq_rel;
1291
1292                                 seq_rel = relation_open(seq_relid, AccessExclusiveLock);
1293
1294                                 /* This check must match AlterSequence! */
1295                                 if (!pg_class_ownercheck(seq_relid, GetUserId()))
1296                                         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
1297                                                                    RelationGetRelationName(seq_rel));
1298
1299                                 seq_relids = lappend_oid(seq_relids, seq_relid);
1300
1301                                 relation_close(seq_rel, NoLock);
1302                         }
1303                 }
1304         }
1305
1306         /* Prepare to catch AFTER triggers. */
1307         AfterTriggerBeginQuery();
1308
1309         /*
1310          * To fire triggers, we'll need an EState as well as a ResultRelInfo for
1311          * each relation.  We don't need to call ExecOpenIndices, though.
1312          */
1313         estate = CreateExecutorState();
1314         resultRelInfos = (ResultRelInfo *)
1315                 palloc(list_length(rels) * sizeof(ResultRelInfo));
1316         resultRelInfo = resultRelInfos;
1317         foreach(cell, rels)
1318         {
1319                 Relation        rel = (Relation) lfirst(cell);
1320
1321                 InitResultRelInfo(resultRelInfo,
1322                                                   rel,
1323                                                   0,    /* dummy rangetable index */
1324                                                   NULL,
1325                                                   0);
1326                 resultRelInfo++;
1327         }
1328         estate->es_result_relations = resultRelInfos;
1329         estate->es_num_result_relations = list_length(rels);
1330
1331         /*
1332          * Process all BEFORE STATEMENT TRUNCATE triggers before we begin
1333          * truncating (this is because one of them might throw an error). Also, if
1334          * we were to allow them to prevent statement execution, that would need
1335          * to be handled here.
1336          */
1337         resultRelInfo = resultRelInfos;
1338         foreach(cell, rels)
1339         {
1340                 estate->es_result_relation_info = resultRelInfo;
1341                 ExecBSTruncateTriggers(estate, resultRelInfo);
1342                 resultRelInfo++;
1343         }
1344
1345         /*
1346          * OK, truncate each table.
1347          */
1348         mySubid = GetCurrentSubTransactionId();
1349
1350         foreach(cell, rels)
1351         {
1352                 Relation        rel = (Relation) lfirst(cell);
1353
1354                 /* Skip partitioned tables as there is nothing to do */
1355                 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1356                         continue;
1357
1358                 /*
1359                  * Normally, we need a transaction-safe truncation here.  However, if
1360                  * the table was either created in the current (sub)transaction or has
1361                  * a new relfilenode in the current (sub)transaction, then we can just
1362                  * truncate it in-place, because a rollback would cause the whole
1363                  * table or the current physical file to be thrown away anyway.
1364                  */
1365                 if (rel->rd_createSubid == mySubid ||
1366                         rel->rd_newRelfilenodeSubid == mySubid)
1367                 {
1368                         /* Immediate, non-rollbackable truncation is OK */
1369                         heap_truncate_one_rel(rel);
1370                 }
1371                 else
1372                 {
1373                         Oid                     heap_relid;
1374                         Oid                     toast_relid;
1375                         MultiXactId minmulti;
1376
1377                         /*
1378                          * This effectively deletes all rows in the table, and may be done
1379                          * in a serializable transaction.  In that case we must record a
1380                          * rw-conflict in to this transaction from each transaction
1381                          * holding a predicate lock on the table.
1382                          */
1383                         CheckTableForSerializableConflictIn(rel);
1384
1385                         minmulti = GetOldestMultiXactId();
1386
1387                         /*
1388                          * Need the full transaction-safe pushups.
1389                          *
1390                          * Create a new empty storage file for the relation, and assign it
1391                          * as the relfilenode value. The old storage file is scheduled for
1392                          * deletion at commit.
1393                          */
1394                         RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
1395                                                                           RecentXmin, minmulti);
1396                         if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
1397                                 heap_create_init_fork(rel);
1398
1399                         heap_relid = RelationGetRelid(rel);
1400                         toast_relid = rel->rd_rel->reltoastrelid;
1401
1402                         /*
1403                          * The same for the toast table, if any.
1404                          */
1405                         if (OidIsValid(toast_relid))
1406                         {
1407                                 rel = relation_open(toast_relid, AccessExclusiveLock);
1408                                 RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
1409                                                                                   RecentXmin, minmulti);
1410                                 if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
1411                                         heap_create_init_fork(rel);
1412                                 heap_close(rel, NoLock);
1413                         }
1414
1415                         /*
1416                          * Reconstruct the indexes to match, and we're done.
1417                          */
1418                         reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST, 0);
1419                 }
1420
1421                 pgstat_count_truncate(rel);
1422         }
1423
1424         /*
1425          * Restart owned sequences if we were asked to.
1426          */
1427         foreach(cell, seq_relids)
1428         {
1429                 Oid                     seq_relid = lfirst_oid(cell);
1430
1431                 ResetSequence(seq_relid);
1432         }
1433
1434         /*
1435          * Process all AFTER STATEMENT TRUNCATE triggers.
1436          */
1437         resultRelInfo = resultRelInfos;
1438         foreach(cell, rels)
1439         {
1440                 estate->es_result_relation_info = resultRelInfo;
1441                 ExecASTruncateTriggers(estate, resultRelInfo);
1442                 resultRelInfo++;
1443         }
1444
1445         /* Handle queued AFTER triggers */
1446         AfterTriggerEndQuery(estate);
1447
1448         /* We can clean up the EState now */
1449         FreeExecutorState(estate);
1450
1451         /* And close the rels (can't do this while EState still holds refs) */
1452         foreach(cell, rels)
1453         {
1454                 Relation        rel = (Relation) lfirst(cell);
1455
1456                 heap_close(rel, NoLock);
1457         }
1458 }
1459
1460 /*
1461  * Check that a given rel is safe to truncate.  Subroutine for ExecuteTruncate
1462  */
1463 static void
1464 truncate_check_rel(Relation rel)
1465 {
1466         AclResult       aclresult;
1467
1468         /*
1469          * Only allow truncate on regular tables and partitioned tables (although,
1470          * the latter are only being included here for the following checks; no
1471          * physical truncation will occur in their case.)
1472          */
1473         if (rel->rd_rel->relkind != RELKIND_RELATION &&
1474                 rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1475                 ereport(ERROR,
1476                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1477                                  errmsg("\"%s\" is not a table",
1478                                                 RelationGetRelationName(rel))));
1479
1480         /* Permissions checks */
1481         aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
1482                                                                   ACL_TRUNCATE);
1483         if (aclresult != ACLCHECK_OK)
1484                 aclcheck_error(aclresult, ACL_KIND_CLASS,
1485                                            RelationGetRelationName(rel));
1486
1487         if (!allowSystemTableMods && IsSystemRelation(rel))
1488                 ereport(ERROR,
1489                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1490                                  errmsg("permission denied: \"%s\" is a system catalog",
1491                                                 RelationGetRelationName(rel))));
1492
1493         /*
1494          * Don't allow truncate on temp tables of other backends ... their local
1495          * buffer manager is not going to cope.
1496          */
1497         if (RELATION_IS_OTHER_TEMP(rel))
1498                 ereport(ERROR,
1499                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1500                           errmsg("cannot truncate temporary tables of other sessions")));
1501
1502         /*
1503          * Also check for active uses of the relation in the current transaction,
1504          * including open scans and pending AFTER trigger events.
1505          */
1506         CheckTableNotInUse(rel, "TRUNCATE");
1507 }
1508
1509 /*
1510  * storage_name
1511  *        returns the name corresponding to a typstorage/attstorage enum value
1512  */
1513 static const char *
1514 storage_name(char c)
1515 {
1516         switch (c)
1517         {
1518                 case 'p':
1519                         return "PLAIN";
1520                 case 'm':
1521                         return "MAIN";
1522                 case 'x':
1523                         return "EXTENDED";
1524                 case 'e':
1525                         return "EXTERNAL";
1526                 default:
1527                         return "???";
1528         }
1529 }
1530
1531 /*----------
1532  * MergeAttributes
1533  *              Returns new schema given initial schema and superclasses.
1534  *
1535  * Input arguments:
1536  * 'schema' is the column/attribute definition for the table. (It's a list
1537  *              of ColumnDef's.) It is destructively changed.
1538  * 'supers' is a list of names (as RangeVar nodes) of parent relations.
1539  * 'relpersistence' is a persistence type of the table.
1540  * 'is_partition' tells if the table is a partition
1541  *
1542  * Output arguments:
1543  * 'supOids' receives a list of the OIDs of the parent relations.
1544  * 'supconstr' receives a list of constraints belonging to the parents,
1545  *              updated as necessary to be valid for the child.
1546  * 'supOidCount' is set to the number of parents that have OID columns.
1547  *
1548  * Return value:
1549  * Completed schema list.
1550  *
1551  * Notes:
1552  *        The order in which the attributes are inherited is very important.
1553  *        Intuitively, the inherited attributes should come first. If a table
1554  *        inherits from multiple parents, the order of those attributes are
1555  *        according to the order of the parents specified in CREATE TABLE.
1556  *
1557  *        Here's an example:
1558  *
1559  *              create table person (name text, age int4, location point);
1560  *              create table emp (salary int4, manager text) inherits(person);
1561  *              create table student (gpa float8) inherits (person);
1562  *              create table stud_emp (percent int4) inherits (emp, student);
1563  *
1564  *        The order of the attributes of stud_emp is:
1565  *
1566  *                                                      person {1:name, 2:age, 3:location}
1567  *                                                      /        \
1568  *                         {6:gpa}      student   emp {4:salary, 5:manager}
1569  *                                                      \        /
1570  *                                                 stud_emp {7:percent}
1571  *
1572  *         If the same attribute name appears multiple times, then it appears
1573  *         in the result table in the proper location for its first appearance.
1574  *
1575  *         Constraints (including NOT NULL constraints) for the child table
1576  *         are the union of all relevant constraints, from both the child schema
1577  *         and parent tables.
1578  *
1579  *         The default value for a child column is defined as:
1580  *              (1) If the child schema specifies a default, that value is used.
1581  *              (2) If neither the child nor any parent specifies a default, then
1582  *                      the column will not have a default.
1583  *              (3) If conflicting defaults are inherited from different parents
1584  *                      (and not overridden by the child), an error is raised.
1585  *              (4) Otherwise the inherited default is used.
1586  *              Rule (3) is new in Postgres 7.1; in earlier releases you got a
1587  *              rather arbitrary choice of which parent default to use.
1588  *----------
1589  */
1590 static List *
1591 MergeAttributes(List *schema, List *supers, char relpersistence,
1592                                 bool is_partition, List **supOids, List **supconstr,
1593                                 int *supOidCount)
1594 {
1595         ListCell   *entry;
1596         List       *inhSchema = NIL;
1597         List       *parentOids = NIL;
1598         List       *constraints = NIL;
1599         int                     parentsWithOids = 0;
1600         bool            have_bogus_defaults = false;
1601         int                     child_attno;
1602         static Node bogus_marker = {0};         /* marks conflicting defaults */
1603         List       *saved_schema = NIL;
1604
1605         /*
1606          * Check for and reject tables with too many columns. We perform this
1607          * check relatively early for two reasons: (a) we don't run the risk of
1608          * overflowing an AttrNumber in subsequent code (b) an O(n^2) algorithm is
1609          * okay if we're processing <= 1600 columns, but could take minutes to
1610          * execute if the user attempts to create a table with hundreds of
1611          * thousands of columns.
1612          *
1613          * Note that we also need to check that we do not exceed this figure after
1614          * including columns from inherited relations.
1615          */
1616         if (list_length(schema) > MaxHeapAttributeNumber)
1617                 ereport(ERROR,
1618                                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
1619                                  errmsg("tables can have at most %d columns",
1620                                                 MaxHeapAttributeNumber)));
1621
1622         /*
1623          * In case of a partition, there are no new column definitions, only dummy
1624          * ColumnDefs created for column constraints.  We merge them with the
1625          * constraints inherited from the parent.
1626          */
1627         if (is_partition)
1628         {
1629                 saved_schema = schema;
1630                 schema = NIL;
1631         }
1632
1633         /*
1634          * Check for duplicate names in the explicit list of attributes.
1635          *
1636          * Although we might consider merging such entries in the same way that we
1637          * handle name conflicts for inherited attributes, it seems to make more
1638          * sense to assume such conflicts are errors.
1639          */
1640         foreach(entry, schema)
1641         {
1642                 ColumnDef  *coldef = lfirst(entry);
1643                 ListCell   *rest = lnext(entry);
1644                 ListCell   *prev = entry;
1645
1646                 if (coldef->typeName == NULL)
1647
1648                         /*
1649                          * Typed table column option that does not belong to a column from
1650                          * the type.  This works because the columns from the type come
1651                          * first in the list.
1652                          */
1653                         ereport(ERROR,
1654                                         (errcode(ERRCODE_UNDEFINED_COLUMN),
1655                                          errmsg("column \"%s\" does not exist",
1656                                                         coldef->colname)));
1657
1658                 while (rest != NULL)
1659                 {
1660                         ColumnDef  *restdef = lfirst(rest);
1661                         ListCell   *next = lnext(rest);         /* need to save it in case we
1662                                                                                                  * delete it */
1663
1664                         if (strcmp(coldef->colname, restdef->colname) == 0)
1665                         {
1666                                 if (coldef->is_from_type)
1667                                 {
1668                                         /*
1669                                          * merge the column options into the column from the type
1670                                          */
1671                                         coldef->is_not_null = restdef->is_not_null;
1672                                         coldef->raw_default = restdef->raw_default;
1673                                         coldef->cooked_default = restdef->cooked_default;
1674                                         coldef->constraints = restdef->constraints;
1675                                         coldef->is_from_type = false;
1676                                         list_delete_cell(schema, rest, prev);
1677                                 }
1678                                 else
1679                                         ereport(ERROR,
1680                                                         (errcode(ERRCODE_DUPLICATE_COLUMN),
1681                                                          errmsg("column \"%s\" specified more than once",
1682                                                                         coldef->colname)));
1683                         }
1684                         prev = rest;
1685                         rest = next;
1686                 }
1687         }
1688
1689         /*
1690          * Scan the parents left-to-right, and merge their attributes to form a
1691          * list of inherited attributes (inhSchema).  Also check to see if we need
1692          * to inherit an OID column.
1693          */
1694         child_attno = 0;
1695         foreach(entry, supers)
1696         {
1697                 RangeVar   *parent = (RangeVar *) lfirst(entry);
1698                 Relation        relation;
1699                 TupleDesc       tupleDesc;
1700                 TupleConstr *constr;
1701                 AttrNumber *newattno;
1702                 AttrNumber      parent_attno;
1703
1704                 /*
1705                  * A self-exclusive lock is needed here.  If two backends attempt to
1706                  * add children to the same parent simultaneously, and that parent has
1707                  * no pre-existing children, then both will attempt to update the
1708                  * parent's relhassubclass field, leading to a "tuple concurrently
1709                  * updated" error.  Also, this interlocks against a concurrent ANALYZE
1710                  * on the parent table, which might otherwise be attempting to clear
1711                  * the parent's relhassubclass field, if its previous children were
1712                  * recently dropped.
1713                  *
1714                  * If the child table is a partition, then we instead grab an
1715                  * exclusive lock on the parent because its partition descriptor will
1716                  * be changed by addition of the new partition.
1717                  */
1718                 if (!is_partition)
1719                         relation = heap_openrv(parent, ShareUpdateExclusiveLock);
1720                 else
1721                         relation = heap_openrv(parent, AccessExclusiveLock);
1722
1723                 /*
1724                  * We do not allow partitioned tables and partitions to participate in
1725                  * regular inheritance.
1726                  */
1727                 if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
1728                         !is_partition)
1729                         ereport(ERROR,
1730                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1731                                          errmsg("cannot inherit from partitioned table \"%s\"",
1732                                                         parent->relname)));
1733                 if (relation->rd_rel->relispartition && !is_partition)
1734                         ereport(ERROR,
1735                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1736                                          errmsg("cannot inherit from partition \"%s\"",
1737                                                         parent->relname)));
1738
1739                 if (relation->rd_rel->relkind != RELKIND_RELATION &&
1740                         relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1741                         relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1742                         ereport(ERROR,
1743                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1744                                          errmsg("inherited relation \"%s\" is not a table or foreign table",
1745                                                         parent->relname)));
1746                 /* Permanent rels cannot inherit from temporary ones */
1747                 if (relpersistence != RELPERSISTENCE_TEMP &&
1748                         relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
1749                         ereport(ERROR,
1750                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1751                                          errmsg(!is_partition
1752                                                         ? "cannot inherit from temporary relation \"%s\""
1753                                                         : "cannot create a permanent relation as partition of temporary relation \"%s\"",
1754                                                         parent->relname)));
1755
1756                 /* If existing rel is temp, it must belong to this session */
1757                 if (relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
1758                         !relation->rd_islocaltemp)
1759                         ereport(ERROR,
1760                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1761                                          errmsg(!is_partition
1762                                 ? "cannot inherit from temporary relation of another session"
1763                                                         : "cannot create as partition of temporary relation of another session")));
1764
1765                 /*
1766                  * We should have an UNDER permission flag for this, but for now,
1767                  * demand that creator of a child table own the parent.
1768                  */
1769                 if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
1770                         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
1771                                                    RelationGetRelationName(relation));
1772
1773                 /*
1774                  * Reject duplications in the list of parents.
1775                  */
1776                 if (list_member_oid(parentOids, RelationGetRelid(relation)))
1777                         ereport(ERROR,
1778                                         (errcode(ERRCODE_DUPLICATE_TABLE),
1779                          errmsg("relation \"%s\" would be inherited from more than once",
1780                                         parent->relname)));
1781
1782                 parentOids = lappend_oid(parentOids, RelationGetRelid(relation));
1783
1784                 if (relation->rd_rel->relhasoids)
1785                         parentsWithOids++;
1786
1787                 tupleDesc = RelationGetDescr(relation);
1788                 constr = tupleDesc->constr;
1789
1790                 /*
1791                  * newattno[] will contain the child-table attribute numbers for the
1792                  * attributes of this parent table.  (They are not the same for
1793                  * parents after the first one, nor if we have dropped columns.)
1794                  */
1795                 newattno = (AttrNumber *)
1796                         palloc0(tupleDesc->natts * sizeof(AttrNumber));
1797
1798                 for (parent_attno = 1; parent_attno <= tupleDesc->natts;
1799                          parent_attno++)
1800                 {
1801                         Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
1802                         char       *attributeName = NameStr(attribute->attname);
1803                         int                     exist_attno;
1804                         ColumnDef  *def;
1805
1806                         /*
1807                          * Ignore dropped columns in the parent.
1808                          */
1809                         if (attribute->attisdropped)
1810                                 continue;               /* leave newattno entry as zero */
1811
1812                         /*
1813                          * Does it conflict with some previously inherited column?
1814                          */
1815                         exist_attno = findAttrByName(attributeName, inhSchema);
1816                         if (exist_attno > 0)
1817                         {
1818                                 Oid                     defTypeId;
1819                                 int32           deftypmod;
1820                                 Oid                     defCollId;
1821
1822                                 /*
1823                                  * Yes, try to merge the two column definitions. They must
1824                                  * have the same type, typmod, and collation.
1825                                  */
1826                                 ereport(NOTICE,
1827                                                 (errmsg("merging multiple inherited definitions of column \"%s\"",
1828                                                                 attributeName)));
1829                                 def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
1830                                 typenameTypeIdAndMod(NULL, def->typeName, &defTypeId, &deftypmod);
1831                                 if (defTypeId != attribute->atttypid ||
1832                                         deftypmod != attribute->atttypmod)
1833                                         ereport(ERROR,
1834                                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
1835                                                 errmsg("inherited column \"%s\" has a type conflict",
1836                                                            attributeName),
1837                                                          errdetail("%s versus %s",
1838                                                                            format_type_with_typemod(defTypeId,
1839                                                                                                                                 deftypmod),
1840                                                                 format_type_with_typemod(attribute->atttypid,
1841                                                                                                         attribute->atttypmod))));
1842                                 defCollId = GetColumnDefCollation(NULL, def, defTypeId);
1843                                 if (defCollId != attribute->attcollation)
1844                                         ereport(ERROR,
1845                                                         (errcode(ERRCODE_COLLATION_MISMATCH),
1846                                         errmsg("inherited column \"%s\" has a collation conflict",
1847                                                    attributeName),
1848                                                          errdetail("\"%s\" versus \"%s\"",
1849                                                                            get_collation_name(defCollId),
1850                                                           get_collation_name(attribute->attcollation))));
1851
1852                                 /* Copy storage parameter */
1853                                 if (def->storage == 0)
1854                                         def->storage = attribute->attstorage;
1855                                 else if (def->storage != attribute->attstorage)
1856                                         ereport(ERROR,
1857                                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
1858                                                          errmsg("inherited column \"%s\" has a storage parameter conflict",
1859                                                                         attributeName),
1860                                                          errdetail("%s versus %s",
1861                                                                            storage_name(def->storage),
1862                                                                            storage_name(attribute->attstorage))));
1863
1864                                 def->inhcount++;
1865                                 /* Merge of NOT NULL constraints = OR 'em together */
1866                                 def->is_not_null |= attribute->attnotnull;
1867                                 /* Default and other constraints are handled below */
1868                                 newattno[parent_attno - 1] = exist_attno;
1869                         }
1870                         else
1871                         {
1872                                 /*
1873                                  * No, create a new inherited column
1874                                  */
1875                                 def = makeNode(ColumnDef);
1876                                 def->colname = pstrdup(attributeName);
1877                                 def->typeName = makeTypeNameFromOid(attribute->atttypid,
1878                                                                                                         attribute->atttypmod);
1879                                 def->inhcount = 1;
1880                                 def->is_local = false;
1881                                 def->is_not_null = attribute->attnotnull;
1882                                 def->is_from_type = false;
1883                                 def->storage = attribute->attstorage;
1884                                 def->raw_default = NULL;
1885                                 def->cooked_default = NULL;
1886                                 def->collClause = NULL;
1887                                 def->collOid = attribute->attcollation;
1888                                 def->constraints = NIL;
1889                                 def->location = -1;
1890                                 inhSchema = lappend(inhSchema, def);
1891                                 newattno[parent_attno - 1] = ++child_attno;
1892                         }
1893
1894                         /*
1895                          * Copy default if any
1896                          */
1897                         if (attribute->atthasdef)
1898                         {
1899                                 Node       *this_default = NULL;
1900                                 AttrDefault *attrdef;
1901                                 int                     i;
1902
1903                                 /* Find default in constraint structure */
1904                                 Assert(constr != NULL);
1905                                 attrdef = constr->defval;
1906                                 for (i = 0; i < constr->num_defval; i++)
1907                                 {
1908                                         if (attrdef[i].adnum == parent_attno)
1909                                         {
1910                                                 this_default = stringToNode(attrdef[i].adbin);
1911                                                 break;
1912                                         }
1913                                 }
1914                                 Assert(this_default != NULL);
1915
1916                                 /*
1917                                  * If default expr could contain any vars, we'd need to fix
1918                                  * 'em, but it can't; so default is ready to apply to child.
1919                                  *
1920                                  * If we already had a default from some prior parent, check
1921                                  * to see if they are the same.  If so, no problem; if not,
1922                                  * mark the column as having a bogus default. Below, we will
1923                                  * complain if the bogus default isn't overridden by the child
1924                                  * schema.
1925                                  */
1926                                 Assert(def->raw_default == NULL);
1927                                 if (def->cooked_default == NULL)
1928                                         def->cooked_default = this_default;
1929                                 else if (!equal(def->cooked_default, this_default))
1930                                 {
1931                                         def->cooked_default = &bogus_marker;
1932                                         have_bogus_defaults = true;
1933                                 }
1934                         }
1935                 }
1936
1937                 /*
1938                  * Now copy the CHECK constraints of this parent, adjusting attnos
1939                  * using the completed newattno[] map.  Identically named constraints
1940                  * are merged if possible, else we throw error.
1941                  */
1942                 if (constr && constr->num_check > 0)
1943                 {
1944                         ConstrCheck *check = constr->check;
1945                         int                     i;
1946
1947                         for (i = 0; i < constr->num_check; i++)
1948                         {
1949                                 char       *name = check[i].ccname;
1950                                 Node       *expr;
1951                                 bool            found_whole_row;
1952
1953                                 /* ignore if the constraint is non-inheritable */
1954                                 if (check[i].ccnoinherit)
1955                                         continue;
1956
1957                                 /* Adjust Vars to match new table's column numbering */
1958                                 expr = map_variable_attnos(stringToNode(check[i].ccbin),
1959                                                                                    1, 0,
1960                                                                                    newattno, tupleDesc->natts,
1961                                                                                    &found_whole_row);
1962
1963                                 /*
1964                                  * For the moment we have to reject whole-row variables. We
1965                                  * could convert them, if we knew the new table's rowtype OID,
1966                                  * but that hasn't been assigned yet.
1967                                  */
1968                                 if (found_whole_row)
1969                                         ereport(ERROR,
1970                                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1971                                                   errmsg("cannot convert whole-row table reference"),
1972                                                          errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
1973                                                                            name,
1974                                                                            RelationGetRelationName(relation))));
1975
1976                                 /* check for duplicate */
1977                                 if (!MergeCheckConstraint(constraints, name, expr))
1978                                 {
1979                                         /* nope, this is a new one */
1980                                         CookedConstraint *cooked;
1981
1982                                         cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
1983                                         cooked->contype = CONSTR_CHECK;
1984                                         cooked->conoid = InvalidOid;            /* until created */
1985                                         cooked->name = pstrdup(name);
1986                                         cooked->attnum = 0; /* not used for constraints */
1987                                         cooked->expr = expr;
1988                                         cooked->skip_validation = false;
1989                                         cooked->is_local = false;
1990                                         cooked->inhcount = 1;
1991                                         cooked->is_no_inherit = false;
1992                                         constraints = lappend(constraints, cooked);
1993                                 }
1994                         }
1995                 }
1996
1997                 pfree(newattno);
1998
1999                 /*
2000                  * Close the parent rel, but keep our lock on it until xact commit.
2001                  * That will prevent someone else from deleting or ALTERing the parent
2002                  * before the child is committed.
2003                  */
2004                 heap_close(relation, NoLock);
2005         }
2006
2007         /*
2008          * If we had no inherited attributes, the result schema is just the
2009          * explicitly declared columns.  Otherwise, we need to merge the declared
2010          * columns into the inherited schema list.  Although, we never have any
2011          * explicitly declared columns if the table is a partition.
2012          */
2013         if (inhSchema != NIL)
2014         {
2015                 int                     schema_attno = 0;
2016
2017                 foreach(entry, schema)
2018                 {
2019                         ColumnDef  *newdef = lfirst(entry);
2020                         char       *attributeName = newdef->colname;
2021                         int                     exist_attno;
2022
2023                         schema_attno++;
2024
2025                         /*
2026                          * Does it conflict with some previously inherited column?
2027                          */
2028                         exist_attno = findAttrByName(attributeName, inhSchema);
2029                         if (exist_attno > 0)
2030                         {
2031                                 ColumnDef  *def;
2032                                 Oid                     defTypeId,
2033                                                         newTypeId;
2034                                 int32           deftypmod,
2035                                                         newtypmod;
2036                                 Oid                     defcollid,
2037                                                         newcollid;
2038
2039                                 /*
2040                                  * Partitions have only one parent and have no column
2041                                  * definitions of their own, so conflict should never occur.
2042                                  */
2043                                 Assert(!is_partition);
2044
2045                                 /*
2046                                  * Yes, try to merge the two column definitions. They must
2047                                  * have the same type, typmod, and collation.
2048                                  */
2049                                 if (exist_attno == schema_attno)
2050                                         ereport(NOTICE,
2051                                         (errmsg("merging column \"%s\" with inherited definition",
2052                                                         attributeName)));
2053                                 else
2054                                         ereport(NOTICE,
2055                                                         (errmsg("moving and merging column \"%s\" with inherited definition", attributeName),
2056                                                          errdetail("User-specified column moved to the position of the inherited column.")));
2057                                 def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
2058                                 typenameTypeIdAndMod(NULL, def->typeName, &defTypeId, &deftypmod);
2059                                 typenameTypeIdAndMod(NULL, newdef->typeName, &newTypeId, &newtypmod);
2060                                 if (defTypeId != newTypeId || deftypmod != newtypmod)
2061                                         ereport(ERROR,
2062                                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
2063                                                          errmsg("column \"%s\" has a type conflict",
2064                                                                         attributeName),
2065                                                          errdetail("%s versus %s",
2066                                                                            format_type_with_typemod(defTypeId,
2067                                                                                                                                 deftypmod),
2068                                                                            format_type_with_typemod(newTypeId,
2069                                                                                                                                 newtypmod))));
2070                                 defcollid = GetColumnDefCollation(NULL, def, defTypeId);
2071                                 newcollid = GetColumnDefCollation(NULL, newdef, newTypeId);
2072                                 if (defcollid != newcollid)
2073                                         ereport(ERROR,
2074                                                         (errcode(ERRCODE_COLLATION_MISMATCH),
2075                                                          errmsg("column \"%s\" has a collation conflict",
2076                                                                         attributeName),
2077                                                          errdetail("\"%s\" versus \"%s\"",
2078                                                                            get_collation_name(defcollid),
2079                                                                            get_collation_name(newcollid))));
2080
2081                                 /* Copy storage parameter */
2082                                 if (def->storage == 0)
2083                                         def->storage = newdef->storage;
2084                                 else if (newdef->storage != 0 && def->storage != newdef->storage)
2085                                         ereport(ERROR,
2086                                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
2087                                          errmsg("column \"%s\" has a storage parameter conflict",
2088                                                         attributeName),
2089                                                          errdetail("%s versus %s",
2090                                                                            storage_name(def->storage),
2091                                                                            storage_name(newdef->storage))));
2092
2093                                 /* Mark the column as locally defined */
2094                                 def->is_local = true;
2095                                 /* Merge of NOT NULL constraints = OR 'em together */
2096                                 def->is_not_null |= newdef->is_not_null;
2097                                 /* If new def has a default, override previous default */
2098                                 if (newdef->raw_default != NULL)
2099                                 {
2100                                         def->raw_default = newdef->raw_default;
2101                                         def->cooked_default = newdef->cooked_default;
2102                                 }
2103                         }
2104                         else
2105                         {
2106                                 /*
2107                                  * No, attach new column to result schema
2108                                  */
2109                                 inhSchema = lappend(inhSchema, newdef);
2110                         }
2111                 }
2112
2113                 schema = inhSchema;
2114
2115                 /*
2116                  * Check that we haven't exceeded the legal # of columns after merging
2117                  * in inherited columns.
2118                  */
2119                 if (list_length(schema) > MaxHeapAttributeNumber)
2120                         ereport(ERROR,
2121                                         (errcode(ERRCODE_TOO_MANY_COLUMNS),
2122                                          errmsg("tables can have at most %d columns",
2123                                                         MaxHeapAttributeNumber)));
2124         }
2125
2126         /*
2127          * Now that we have the column definition list for a partition, we can
2128          * check whether the columns referenced in the column constraint specs
2129          * actually exist.  Also, we merge the constraints into the corresponding
2130          * column definitions.
2131          */
2132         if (is_partition && list_length(saved_schema) > 0)
2133         {
2134                 schema = list_concat(schema, saved_schema);
2135
2136                 foreach(entry, schema)
2137                 {
2138                         ColumnDef  *coldef = lfirst(entry);
2139                         ListCell   *rest = lnext(entry);
2140                         ListCell   *prev = entry;
2141
2142                         /*
2143                          * Partition column option that does not belong to a column from
2144                          * the parent.  This works because the columns from the parent
2145                          * come first in the list (see above).
2146                          */
2147                         if (coldef->typeName == NULL)
2148                                 ereport(ERROR,
2149                                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
2150                                                  errmsg("column \"%s\" does not exist",
2151                                                                 coldef->colname)));
2152                         while (rest != NULL)
2153                         {
2154                                 ColumnDef  *restdef = lfirst(rest);
2155                                 ListCell   *next = lnext(rest); /* need to save it in case we
2156                                                                                                  * delete it */
2157
2158                                 if (strcmp(coldef->colname, restdef->colname) == 0)
2159                                 {
2160                                         /*
2161                                          * merge the column options into the column from the
2162                                          * parent
2163                                          */
2164                                         coldef->is_not_null = restdef->is_not_null;
2165                                         coldef->raw_default = restdef->raw_default;
2166                                         coldef->cooked_default = restdef->cooked_default;
2167                                         coldef->constraints = restdef->constraints;
2168                                         list_delete_cell(schema, rest, prev);
2169                                 }
2170                                 prev = rest;
2171                                 rest = next;
2172                         }
2173                 }
2174         }
2175
2176         /*
2177          * If we found any conflicting parent default values, check to make sure
2178          * they were overridden by the child.
2179          */
2180         if (have_bogus_defaults)
2181         {
2182                 foreach(entry, schema)
2183                 {
2184                         ColumnDef  *def = lfirst(entry);
2185
2186                         if (def->cooked_default == &bogus_marker)
2187                                 ereport(ERROR,
2188                                                 (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
2189                                   errmsg("column \"%s\" inherits conflicting default values",
2190                                                  def->colname),
2191                                                  errhint("To resolve the conflict, specify a default explicitly.")));
2192                 }
2193         }
2194
2195         *supOids = parentOids;
2196         *supconstr = constraints;
2197         *supOidCount = parentsWithOids;
2198         return schema;
2199 }
2200
2201
2202 /*
2203  * MergeCheckConstraint
2204  *              Try to merge an inherited CHECK constraint with previous ones
2205  *
2206  * If we inherit identically-named constraints from multiple parents, we must
2207  * merge them, or throw an error if they don't have identical definitions.
2208  *
2209  * constraints is a list of CookedConstraint structs for previous constraints.
2210  *
2211  * Returns TRUE if merged (constraint is a duplicate), or FALSE if it's
2212  * got a so-far-unique name, or throws error if conflict.
2213  */
2214 static bool
2215 MergeCheckConstraint(List *constraints, char *name, Node *expr)
2216 {
2217         ListCell   *lc;
2218
2219         foreach(lc, constraints)
2220         {
2221                 CookedConstraint *ccon = (CookedConstraint *) lfirst(lc);
2222
2223                 Assert(ccon->contype == CONSTR_CHECK);
2224
2225                 /* Non-matching names never conflict */
2226                 if (strcmp(ccon->name, name) != 0)
2227                         continue;
2228
2229                 if (equal(expr, ccon->expr))
2230                 {
2231                         /* OK to merge */
2232                         ccon->inhcount++;
2233                         return true;
2234                 }
2235
2236                 ereport(ERROR,
2237                                 (errcode(ERRCODE_DUPLICATE_OBJECT),
2238                                  errmsg("check constraint name \"%s\" appears multiple times but with different expressions",
2239                                                 name)));
2240         }
2241
2242         return false;
2243 }
2244
2245
2246 /*
2247  * StoreCatalogInheritance
2248  *              Updates the system catalogs with proper inheritance information.
2249  *
2250  * supers is a list of the OIDs of the new relation's direct ancestors.
2251  */
2252 static void
2253 StoreCatalogInheritance(Oid relationId, List *supers,
2254                                                 bool child_is_partition)
2255 {
2256         Relation        relation;
2257         int16           seqNumber;
2258         ListCell   *entry;
2259
2260         /*
2261          * sanity checks
2262          */
2263         AssertArg(OidIsValid(relationId));
2264
2265         if (supers == NIL)
2266                 return;
2267
2268         /*
2269          * Store INHERITS information in pg_inherits using direct ancestors only.
2270          * Also enter dependencies on the direct ancestors, and make sure they are
2271          * marked with relhassubclass = true.
2272          *
2273          * (Once upon a time, both direct and indirect ancestors were found here
2274          * and then entered into pg_ipl.  Since that catalog doesn't exist
2275          * anymore, there's no need to look for indirect ancestors.)
2276          */
2277         relation = heap_open(InheritsRelationId, RowExclusiveLock);
2278
2279         seqNumber = 1;
2280         foreach(entry, supers)
2281         {
2282                 Oid                     parentOid = lfirst_oid(entry);
2283
2284                 StoreCatalogInheritance1(relationId, parentOid, seqNumber, relation,
2285                                                                  child_is_partition);
2286                 seqNumber++;
2287         }
2288
2289         heap_close(relation, RowExclusiveLock);
2290 }
2291
2292 /*
2293  * Make catalog entries showing relationId as being an inheritance child
2294  * of parentOid.  inhRelation is the already-opened pg_inherits catalog.
2295  */
2296 static void
2297 StoreCatalogInheritance1(Oid relationId, Oid parentOid,
2298                                                  int16 seqNumber, Relation inhRelation,
2299                                                  bool child_is_partition)
2300 {
2301         TupleDesc       desc = RelationGetDescr(inhRelation);
2302         Datum           values[Natts_pg_inherits];
2303         bool            nulls[Natts_pg_inherits];
2304         ObjectAddress childobject,
2305                                 parentobject;
2306         HeapTuple       tuple;
2307
2308         /*
2309          * Make the pg_inherits entry
2310          */
2311         values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId);
2312         values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid);
2313         values[Anum_pg_inherits_inhseqno - 1] = Int16GetDatum(seqNumber);
2314
2315         memset(nulls, 0, sizeof(nulls));
2316
2317         tuple = heap_form_tuple(desc, values, nulls);
2318
2319         CatalogTupleInsert(inhRelation, tuple);
2320
2321         heap_freetuple(tuple);
2322
2323         /*
2324          * Store a dependency too
2325          */
2326         parentobject.classId = RelationRelationId;
2327         parentobject.objectId = parentOid;
2328         parentobject.objectSubId = 0;
2329         childobject.classId = RelationRelationId;
2330         childobject.objectId = relationId;
2331         childobject.objectSubId = 0;
2332
2333         /*
2334          * Partition tables are expected to be dropped when the parent partitioned
2335          * table gets dropped.
2336          */
2337         if (child_is_partition)
2338                 recordDependencyOn(&childobject, &parentobject, DEPENDENCY_AUTO);
2339         else
2340                 recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL);
2341
2342         /*
2343          * Post creation hook of this inheritance. Since object_access_hook
2344          * doesn't take multiple object identifiers, we relay oid of parent
2345          * relation using auxiliary_id argument.
2346          */
2347         InvokeObjectPostAlterHookArg(InheritsRelationId,
2348                                                                  relationId, 0,
2349                                                                  parentOid, false);
2350
2351         /*
2352          * Mark the parent as having subclasses.
2353          */
2354         SetRelationHasSubclass(parentOid, true);
2355 }
2356
2357 /*
2358  * Look for an existing schema entry with the given name.
2359  *
2360  * Returns the index (starting with 1) if attribute already exists in schema,
2361  * 0 if it doesn't.
2362  */
2363 static int
2364 findAttrByName(const char *attributeName, List *schema)
2365 {
2366         ListCell   *s;
2367         int                     i = 1;
2368
2369         foreach(s, schema)
2370         {
2371                 ColumnDef  *def = lfirst(s);
2372
2373                 if (strcmp(attributeName, def->colname) == 0)
2374                         return i;
2375
2376                 i++;
2377         }
2378         return 0;
2379 }
2380
2381
2382 /*
2383  * SetRelationHasSubclass
2384  *              Set the value of the relation's relhassubclass field in pg_class.
2385  *
2386  * NOTE: caller must be holding an appropriate lock on the relation.
2387  * ShareUpdateExclusiveLock is sufficient.
2388  *
2389  * NOTE: an important side-effect of this operation is that an SI invalidation
2390  * message is sent out to all backends --- including me --- causing plans
2391  * referencing the relation to be rebuilt with the new list of children.
2392  * This must happen even if we find that no change is needed in the pg_class
2393  * row.
2394  */
2395 void
2396 SetRelationHasSubclass(Oid relationId, bool relhassubclass)
2397 {
2398         Relation        relationRelation;
2399         HeapTuple       tuple;
2400         Form_pg_class classtuple;
2401
2402         /*
2403          * Fetch a modifiable copy of the tuple, modify it, update pg_class.
2404          */
2405         relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
2406         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
2407         if (!HeapTupleIsValid(tuple))
2408                 elog(ERROR, "cache lookup failed for relation %u", relationId);
2409         classtuple = (Form_pg_class) GETSTRUCT(tuple);
2410
2411         if (classtuple->relhassubclass != relhassubclass)
2412         {
2413                 classtuple->relhassubclass = relhassubclass;
2414                 CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
2415         }
2416         else
2417         {
2418                 /* no need to change tuple, but force relcache rebuild anyway */
2419                 CacheInvalidateRelcacheByTuple(tuple);
2420         }
2421
2422         heap_freetuple(tuple);
2423         heap_close(relationRelation, RowExclusiveLock);
2424 }
2425
2426 /*
2427  *              renameatt_check                 - basic sanity checks before attribute rename
2428  */
2429 static void
2430 renameatt_check(Oid myrelid, Form_pg_class classform, bool recursing)
2431 {
2432         char            relkind = classform->relkind;
2433
2434         if (classform->reloftype && !recursing)
2435                 ereport(ERROR,
2436                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2437                                  errmsg("cannot rename column of typed table")));
2438
2439         /*
2440          * Renaming the columns of sequences or toast tables doesn't actually
2441          * break anything from the system's point of view, since internal
2442          * references are by attnum.  But it doesn't seem right to allow users to
2443          * change names that are hardcoded into the system, hence the following
2444          * restriction.
2445          */
2446         if (relkind != RELKIND_RELATION &&
2447                 relkind != RELKIND_VIEW &&
2448                 relkind != RELKIND_MATVIEW &&
2449                 relkind != RELKIND_COMPOSITE_TYPE &&
2450                 relkind != RELKIND_INDEX &&
2451                 relkind != RELKIND_FOREIGN_TABLE &&
2452                 relkind != RELKIND_PARTITIONED_TABLE)
2453                 ereport(ERROR,
2454                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2455                                  errmsg("\"%s\" is not a table, view, materialized view, composite type, index, or foreign table",
2456                                                 NameStr(classform->relname))));
2457
2458         /*
2459          * permissions checking.  only the owner of a class can change its schema.
2460          */
2461         if (!pg_class_ownercheck(myrelid, GetUserId()))
2462                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
2463                                            NameStr(classform->relname));
2464         if (!allowSystemTableMods && IsSystemClass(myrelid, classform))
2465                 ereport(ERROR,
2466                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2467                                  errmsg("permission denied: \"%s\" is a system catalog",
2468                                                 NameStr(classform->relname))));
2469 }
2470
2471 /*
2472  *              renameatt_internal              - workhorse for renameatt
2473  *
2474  * Return value is the attribute number in the 'myrelid' relation.
2475  */
2476 static AttrNumber
2477 renameatt_internal(Oid myrelid,
2478                                    const char *oldattname,
2479                                    const char *newattname,
2480                                    bool recurse,
2481                                    bool recursing,
2482                                    int expected_parents,
2483                                    DropBehavior behavior)
2484 {
2485         Relation        targetrelation;
2486         Relation        attrelation;
2487         HeapTuple       atttup;
2488         Form_pg_attribute attform;
2489         AttrNumber      attnum;
2490
2491         /*
2492          * Grab an exclusive lock on the target table, which we will NOT release
2493          * until end of transaction.
2494          */
2495         targetrelation = relation_open(myrelid, AccessExclusiveLock);
2496         renameatt_check(myrelid, RelationGetForm(targetrelation), recursing);
2497
2498         /*
2499          * if the 'recurse' flag is set then we are supposed to rename this
2500          * attribute in all classes that inherit from 'relname' (as well as in
2501          * 'relname').
2502          *
2503          * any permissions or problems with duplicate attributes will cause the
2504          * whole transaction to abort, which is what we want -- all or nothing.
2505          */
2506         if (recurse)
2507         {
2508                 List       *child_oids,
2509                                    *child_numparents;
2510                 ListCell   *lo,
2511                                    *li;
2512
2513                 /*
2514                  * we need the number of parents for each child so that the recursive
2515                  * calls to renameatt() can determine whether there are any parents
2516                  * outside the inheritance hierarchy being processed.
2517                  */
2518                 child_oids = find_all_inheritors(myrelid, AccessExclusiveLock,
2519                                                                                  &child_numparents);
2520
2521                 /*
2522                  * find_all_inheritors does the recursive search of the inheritance
2523                  * hierarchy, so all we have to do is process all of the relids in the
2524                  * list that it returns.
2525                  */
2526                 forboth(lo, child_oids, li, child_numparents)
2527                 {
2528                         Oid                     childrelid = lfirst_oid(lo);
2529                         int                     numparents = lfirst_int(li);
2530
2531                         if (childrelid == myrelid)
2532                                 continue;
2533                         /* note we need not recurse again */
2534                         renameatt_internal(childrelid, oldattname, newattname, false, true, numparents, behavior);
2535                 }
2536         }
2537         else
2538         {
2539                 /*
2540                  * If we are told not to recurse, there had better not be any child
2541                  * tables; else the rename would put them out of step.
2542                  *
2543                  * expected_parents will only be 0 if we are not already recursing.
2544                  */
2545                 if (expected_parents == 0 &&
2546                         find_inheritance_children(myrelid, NoLock) != NIL)
2547                         ereport(ERROR,
2548                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2549                                          errmsg("inherited column \"%s\" must be renamed in child tables too",
2550                                                         oldattname)));
2551         }
2552
2553         /* rename attributes in typed tables of composite type */
2554         if (targetrelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
2555         {
2556                 List       *child_oids;
2557                 ListCell   *lo;
2558
2559                 child_oids = find_typed_table_dependencies(targetrelation->rd_rel->reltype,
2560                                                                          RelationGetRelationName(targetrelation),
2561                                                                                                    behavior);
2562
2563                 foreach(lo, child_oids)
2564                         renameatt_internal(lfirst_oid(lo), oldattname, newattname, true, true, 0, behavior);
2565         }
2566
2567         attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
2568
2569         atttup = SearchSysCacheCopyAttName(myrelid, oldattname);
2570         if (!HeapTupleIsValid(atttup))
2571                 ereport(ERROR,
2572                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
2573                                  errmsg("column \"%s\" does not exist",
2574                                                 oldattname)));
2575         attform = (Form_pg_attribute) GETSTRUCT(atttup);
2576
2577         attnum = attform->attnum;
2578         if (attnum <= 0)
2579                 ereport(ERROR,
2580                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2581                                  errmsg("cannot rename system column \"%s\"",
2582                                                 oldattname)));
2583
2584         /*
2585          * if the attribute is inherited, forbid the renaming.  if this is a
2586          * top-level call to renameatt(), then expected_parents will be 0, so the
2587          * effect of this code will be to prohibit the renaming if the attribute
2588          * is inherited at all.  if this is a recursive call to renameatt(),
2589          * expected_parents will be the number of parents the current relation has
2590          * within the inheritance hierarchy being processed, so we'll prohibit the
2591          * renaming only if there are additional parents from elsewhere.
2592          */
2593         if (attform->attinhcount > expected_parents)
2594                 ereport(ERROR,
2595                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2596                                  errmsg("cannot rename inherited column \"%s\"",
2597                                                 oldattname)));
2598
2599         /* new name should not already exist */
2600         (void) check_for_column_name_collision(targetrelation, newattname, false);
2601
2602         /* apply the update */
2603         namestrcpy(&(attform->attname), newattname);
2604
2605         CatalogTupleUpdate(attrelation, &atttup->t_self, atttup);
2606
2607         InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum);
2608
2609         heap_freetuple(atttup);
2610
2611         heap_close(attrelation, RowExclusiveLock);
2612
2613         relation_close(targetrelation, NoLock);         /* close rel but keep lock */
2614
2615         return attnum;
2616 }
2617
2618 /*
2619  * Perform permissions and integrity checks before acquiring a relation lock.
2620  */
2621 static void
2622 RangeVarCallbackForRenameAttribute(const RangeVar *rv, Oid relid, Oid oldrelid,
2623                                                                    void *arg)
2624 {
2625         HeapTuple       tuple;
2626         Form_pg_class form;
2627
2628         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
2629         if (!HeapTupleIsValid(tuple))
2630                 return;                                 /* concurrently dropped */
2631         form = (Form_pg_class) GETSTRUCT(tuple);
2632         renameatt_check(relid, form, false);
2633         ReleaseSysCache(tuple);
2634 }
2635
2636 /*
2637  *              renameatt               - changes the name of an attribute in a relation
2638  *
2639  * The returned ObjectAddress is that of the renamed column.
2640  */
2641 ObjectAddress
2642 renameatt(RenameStmt *stmt)
2643 {
2644         Oid                     relid;
2645         AttrNumber      attnum;
2646         ObjectAddress address;
2647
2648         /* lock level taken here should match renameatt_internal */
2649         relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
2650                                                                          stmt->missing_ok, false,
2651                                                                          RangeVarCallbackForRenameAttribute,
2652                                                                          NULL);
2653
2654         if (!OidIsValid(relid))
2655         {
2656                 ereport(NOTICE,
2657                                 (errmsg("relation \"%s\" does not exist, skipping",
2658                                                 stmt->relation->relname)));
2659                 return InvalidObjectAddress;
2660         }
2661
2662         attnum =
2663                 renameatt_internal(relid,
2664                                                    stmt->subname,               /* old att name */
2665                                                    stmt->newname,               /* new att name */
2666                                                    stmt->relation->inh, /* recursive? */
2667                                                    false,               /* recursing? */
2668                                                    0,   /* expected inhcount */
2669                                                    stmt->behavior);
2670
2671         ObjectAddressSubSet(address, RelationRelationId, relid, attnum);
2672
2673         return address;
2674 }
2675
2676 /*
2677  * same logic as renameatt_internal
2678  */
2679 static ObjectAddress
2680 rename_constraint_internal(Oid myrelid,
2681                                                    Oid mytypid,
2682                                                    const char *oldconname,
2683                                                    const char *newconname,
2684                                                    bool recurse,
2685                                                    bool recursing,
2686                                                    int expected_parents)
2687 {
2688         Relation        targetrelation = NULL;
2689         Oid                     constraintOid;
2690         HeapTuple       tuple;
2691         Form_pg_constraint con;
2692         ObjectAddress address;
2693
2694         AssertArg(!myrelid || !mytypid);
2695
2696         if (mytypid)
2697         {
2698                 constraintOid = get_domain_constraint_oid(mytypid, oldconname, false);
2699         }
2700         else
2701         {
2702                 targetrelation = relation_open(myrelid, AccessExclusiveLock);
2703
2704                 /*
2705                  * don't tell it whether we're recursing; we allow changing typed
2706                  * tables here
2707                  */
2708                 renameatt_check(myrelid, RelationGetForm(targetrelation), false);
2709
2710                 constraintOid = get_relation_constraint_oid(myrelid, oldconname, false);
2711         }
2712
2713         tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintOid));
2714         if (!HeapTupleIsValid(tuple))
2715                 elog(ERROR, "cache lookup failed for constraint %u",
2716                          constraintOid);
2717         con = (Form_pg_constraint) GETSTRUCT(tuple);
2718
2719         if (myrelid && con->contype == CONSTRAINT_CHECK && !con->connoinherit)
2720         {
2721                 if (recurse)
2722                 {
2723                         List       *child_oids,
2724                                            *child_numparents;
2725                         ListCell   *lo,
2726                                            *li;
2727
2728                         child_oids = find_all_inheritors(myrelid, AccessExclusiveLock,
2729                                                                                          &child_numparents);
2730
2731                         forboth(lo, child_oids, li, child_numparents)
2732                         {
2733                                 Oid                     childrelid = lfirst_oid(lo);
2734                                 int                     numparents = lfirst_int(li);
2735
2736                                 if (childrelid == myrelid)
2737                                         continue;
2738
2739                                 rename_constraint_internal(childrelid, InvalidOid, oldconname, newconname, false, true, numparents);
2740                         }
2741                 }
2742                 else
2743                 {
2744                         if (expected_parents == 0 &&
2745                                 find_inheritance_children(myrelid, NoLock) != NIL)
2746                                 ereport(ERROR,
2747                                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2748                                                  errmsg("inherited constraint \"%s\" must be renamed in child tables too",
2749                                                                 oldconname)));
2750                 }
2751
2752                 if (con->coninhcount > expected_parents)
2753                         ereport(ERROR,
2754                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
2755                                          errmsg("cannot rename inherited constraint \"%s\"",
2756                                                         oldconname)));
2757         }
2758
2759         if (con->conindid
2760                 && (con->contype == CONSTRAINT_PRIMARY
2761                         || con->contype == CONSTRAINT_UNIQUE
2762                         || con->contype == CONSTRAINT_EXCLUSION))
2763                 /* rename the index; this renames the constraint as well */
2764                 RenameRelationInternal(con->conindid, newconname, false);
2765         else
2766                 RenameConstraintById(constraintOid, newconname);
2767
2768         ObjectAddressSet(address, ConstraintRelationId, constraintOid);
2769
2770         ReleaseSysCache(tuple);
2771
2772         if (targetrelation)
2773                 relation_close(targetrelation, NoLock); /* close rel but keep lock */
2774
2775         return address;
2776 }
2777
2778 ObjectAddress
2779 RenameConstraint(RenameStmt *stmt)
2780 {
2781         Oid                     relid = InvalidOid;
2782         Oid                     typid = InvalidOid;
2783
2784         if (stmt->renameType == OBJECT_DOMCONSTRAINT)
2785         {
2786                 Relation        rel;
2787                 HeapTuple       tup;
2788
2789                 typid = typenameTypeId(NULL, makeTypeNameFromNameList(castNode(List, stmt->object)));
2790                 rel = heap_open(TypeRelationId, RowExclusiveLock);
2791                 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
2792                 if (!HeapTupleIsValid(tup))
2793                         elog(ERROR, "cache lookup failed for type %u", typid);
2794                 checkDomainOwner(tup);
2795                 ReleaseSysCache(tup);
2796                 heap_close(rel, NoLock);
2797         }
2798         else
2799         {
2800                 /* lock level taken here should match rename_constraint_internal */
2801                 relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
2802                                                                                  stmt->missing_ok, false,
2803                                                                                  RangeVarCallbackForRenameAttribute,
2804                                                                                  NULL);
2805                 if (!OidIsValid(relid))
2806                 {
2807                         ereport(NOTICE,
2808                                         (errmsg("relation \"%s\" does not exist, skipping",
2809                                                         stmt->relation->relname)));
2810                         return InvalidObjectAddress;
2811                 }
2812         }
2813
2814         return
2815                 rename_constraint_internal(relid, typid,
2816                                                                    stmt->subname,
2817                                                                    stmt->newname,
2818                                                                    (stmt->relation &&
2819                                                                         stmt->relation->inh),           /* recursive? */
2820                                                                    false,               /* recursing? */
2821                                                                    0 /* expected inhcount */ );
2822
2823 }
2824
2825 /*
2826  * Execute ALTER TABLE/INDEX/SEQUENCE/VIEW/MATERIALIZED VIEW/FOREIGN TABLE
2827  * RENAME
2828  */
2829 ObjectAddress
2830 RenameRelation(RenameStmt *stmt)
2831 {
2832         Oid                     relid;
2833         ObjectAddress address;
2834
2835         /*
2836          * Grab an exclusive lock on the target table, index, sequence, view,
2837          * materialized view, or foreign table, which we will NOT release until
2838          * end of transaction.
2839          *
2840          * Lock level used here should match RenameRelationInternal, to avoid lock
2841          * escalation.
2842          */
2843         relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
2844                                                                          stmt->missing_ok, false,
2845                                                                          RangeVarCallbackForAlterRelation,
2846                                                                          (void *) stmt);
2847
2848         if (!OidIsValid(relid))
2849         {
2850                 ereport(NOTICE,
2851                                 (errmsg("relation \"%s\" does not exist, skipping",
2852                                                 stmt->relation->relname)));
2853                 return InvalidObjectAddress;
2854         }
2855
2856         /* Do the work */
2857         RenameRelationInternal(relid, stmt->newname, false);
2858
2859         ObjectAddressSet(address, RelationRelationId, relid);
2860
2861         return address;
2862 }
2863
2864 /*
2865  *              RenameRelationInternal - change the name of a relation
2866  *
2867  *              XXX - When renaming sequences, we don't bother to modify the
2868  *                        sequence name that is stored within the sequence itself
2869  *                        (this would cause problems with MVCC). In the future,
2870  *                        the sequence name should probably be removed from the
2871  *                        sequence, AFAIK there's no need for it to be there.
2872  */
2873 void
2874 RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
2875 {
2876         Relation        targetrelation;
2877         Relation        relrelation;    /* for RELATION relation */
2878         HeapTuple       reltup;
2879         Form_pg_class relform;
2880         Oid                     namespaceId;
2881
2882         /*
2883          * Grab an exclusive lock on the target table, index, sequence, view,
2884          * materialized view, or foreign table, which we will NOT release until
2885          * end of transaction.
2886          */
2887         targetrelation = relation_open(myrelid, AccessExclusiveLock);
2888         namespaceId = RelationGetNamespace(targetrelation);
2889
2890         /*
2891          * Find relation's pg_class tuple, and make sure newrelname isn't in use.
2892          */
2893         relrelation = heap_open(RelationRelationId, RowExclusiveLock);
2894
2895         reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
2896         if (!HeapTupleIsValid(reltup))          /* shouldn't happen */
2897                 elog(ERROR, "cache lookup failed for relation %u", myrelid);
2898         relform = (Form_pg_class) GETSTRUCT(reltup);
2899
2900         if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
2901                 ereport(ERROR,
2902                                 (errcode(ERRCODE_DUPLICATE_TABLE),
2903                                  errmsg("relation \"%s\" already exists",
2904                                                 newrelname)));
2905
2906         /*
2907          * Update pg_class tuple with new relname.  (Scribbling on reltup is OK
2908          * because it's a copy...)
2909          */
2910         namestrcpy(&(relform->relname), newrelname);
2911
2912         CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
2913
2914         InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0,
2915                                                                  InvalidOid, is_internal);
2916
2917         heap_freetuple(reltup);
2918         heap_close(relrelation, RowExclusiveLock);
2919
2920         /*
2921          * Also rename the associated type, if any.
2922          */
2923         if (OidIsValid(targetrelation->rd_rel->reltype))
2924                 RenameTypeInternal(targetrelation->rd_rel->reltype,
2925                                                    newrelname, namespaceId);
2926
2927         /*
2928          * Also rename the associated constraint, if any.
2929          */
2930         if (targetrelation->rd_rel->relkind == RELKIND_INDEX)
2931         {
2932                 Oid                     constraintId = get_index_constraint(myrelid);
2933
2934                 if (OidIsValid(constraintId))
2935                         RenameConstraintById(constraintId, newrelname);
2936         }
2937
2938         /*
2939          * Close rel, but keep exclusive lock!
2940          */
2941         relation_close(targetrelation, NoLock);
2942 }
2943
2944 /*
2945  * Disallow ALTER TABLE (and similar commands) when the current backend has
2946  * any open reference to the target table besides the one just acquired by
2947  * the calling command; this implies there's an open cursor or active plan.
2948  * We need this check because our lock doesn't protect us against stomping
2949  * on our own foot, only other people's feet!
2950  *
2951  * For ALTER TABLE, the only case known to cause serious trouble is ALTER
2952  * COLUMN TYPE, and some changes are obviously pretty benign, so this could
2953  * possibly be relaxed to only error out for certain types of alterations.
2954  * But the use-case for allowing any of these things is not obvious, so we
2955  * won't work hard at it for now.
2956  *
2957  * We also reject these commands if there are any pending AFTER trigger events
2958  * for the rel.  This is certainly necessary for the rewriting variants of
2959  * ALTER TABLE, because they don't preserve tuple TIDs and so the pending
2960  * events would try to fetch the wrong tuples.  It might be overly cautious
2961  * in other cases, but again it seems better to err on the side of paranoia.
2962  *
2963  * REINDEX calls this with "rel" referencing the index to be rebuilt; here
2964  * we are worried about active indexscans on the index.  The trigger-event
2965  * check can be skipped, since we are doing no damage to the parent table.
2966  *
2967  * The statement name (eg, "ALTER TABLE") is passed for use in error messages.
2968  */
2969 void
2970 CheckTableNotInUse(Relation rel, const char *stmt)
2971 {
2972         int                     expected_refcnt;
2973
2974         expected_refcnt = rel->rd_isnailed ? 2 : 1;
2975         if (rel->rd_refcnt != expected_refcnt)
2976                 ereport(ERROR,
2977                                 (errcode(ERRCODE_OBJECT_IN_USE),
2978                 /* translator: first %s is a SQL command, eg ALTER TABLE */
2979                                  errmsg("cannot %s \"%s\" because "
2980                                                 "it is being used by active queries in this session",
2981                                                 stmt, RelationGetRelationName(rel))));
2982
2983         if (rel->rd_rel->relkind != RELKIND_INDEX &&
2984                 AfterTriggerPendingOnRel(RelationGetRelid(rel)))
2985                 ereport(ERROR,
2986                                 (errcode(ERRCODE_OBJECT_IN_USE),
2987                 /* translator: first %s is a SQL command, eg ALTER TABLE */
2988                                  errmsg("cannot %s \"%s\" because "
2989                                                 "it has pending trigger events",
2990                                                 stmt, RelationGetRelationName(rel))));
2991 }
2992
2993 /*
2994  * AlterTableLookupRelation
2995  *              Look up, and lock, the OID for the relation named by an alter table
2996  *              statement.
2997  */
2998 Oid
2999 AlterTableLookupRelation(AlterTableStmt *stmt, LOCKMODE lockmode)
3000 {
3001         return RangeVarGetRelidExtended(stmt->relation, lockmode, stmt->missing_ok, false,
3002                                                                         RangeVarCallbackForAlterRelation,
3003                                                                         (void *) stmt);
3004 }
3005
3006 /*
3007  * AlterTable
3008  *              Execute ALTER TABLE, which can be a list of subcommands
3009  *
3010  * ALTER TABLE is performed in three phases:
3011  *              1. Examine subcommands and perform pre-transformation checking.
3012  *              2. Update system catalogs.
3013  *              3. Scan table(s) to check new constraints, and optionally recopy
3014  *                 the data into new table(s).
3015  * Phase 3 is not performed unless one or more of the subcommands requires
3016  * it.  The intention of this design is to allow multiple independent
3017  * updates of the table schema to be performed with only one pass over the
3018  * data.
3019  *
3020  * ATPrepCmd performs phase 1.  A "work queue" entry is created for
3021  * each table to be affected (there may be multiple affected tables if the
3022  * commands traverse a table inheritance hierarchy).  Also we do preliminary
3023  * validation of the subcommands, including parse transformation of those
3024  * expressions that need to be evaluated with respect to the old table
3025  * schema.
3026  *
3027  * ATRewriteCatalogs performs phase 2 for each affected table.  (Note that
3028  * phases 2 and 3 normally do no explicit recursion, since phase 1 already
3029  * did it --- although some subcommands have to recurse in phase 2 instead.)
3030  * Certain subcommands need to be performed before others to avoid
3031  * unnecessary conflicts; for example, DROP COLUMN should come before
3032  * ADD COLUMN.  Therefore phase 1 divides the subcommands into multiple
3033  * lists, one for each logical "pass" of phase 2.
3034  *
3035  * ATRewriteTables performs phase 3 for those tables that need it.
3036  *
3037  * Thanks to the magic of MVCC, an error anywhere along the way rolls back
3038  * the whole operation; we don't have to do anything special to clean up.
3039  *
3040  * The caller must lock the relation, with an appropriate lock level
3041  * for the subcommands requested, using AlterTableGetLockLevel(stmt->cmds)
3042  * or higher. We pass the lock level down
3043  * so that we can apply it recursively to inherited tables. Note that the
3044  * lock level we want as we recurse might well be higher than required for
3045  * that specific subcommand. So we pass down the overall lock requirement,
3046  * rather than reassess it at lower levels.
3047  */
3048 void
3049 AlterTable(Oid relid, LOCKMODE lockmode, AlterTableStmt *stmt)
3050 {
3051         Relation        rel;
3052
3053         /* Caller is required to provide an adequate lock. */
3054         rel = relation_open(relid, NoLock);
3055
3056         CheckTableNotInUse(rel, "ALTER TABLE");
3057
3058         ATController(stmt, rel, stmt->cmds, stmt->relation->inh, lockmode);
3059 }
3060
3061 /*
3062  * AlterTableInternal
3063  *
3064  * ALTER TABLE with target specified by OID
3065  *
3066  * We do not reject if the relation is already open, because it's quite
3067  * likely that one or more layers of caller have it open.  That means it
3068  * is unsafe to use this entry point for alterations that could break
3069  * existing query plans.  On the assumption it's not used for such, we
3070  * don't have to reject pending AFTER triggers, either.
3071  */
3072 void
3073 AlterTableInternal(Oid relid, List *cmds, bool recurse)
3074 {
3075         Relation        rel;
3076         LOCKMODE        lockmode = AlterTableGetLockLevel(cmds);
3077
3078         rel = relation_open(relid, lockmode);
3079
3080         EventTriggerAlterTableRelid(relid);
3081
3082         ATController(NULL, rel, cmds, recurse, lockmode);
3083 }
3084
3085 /*
3086  * AlterTableGetLockLevel
3087  *
3088  * Sets the overall lock level required for the supplied list of subcommands.
3089  * Policy for doing this set according to needs of AlterTable(), see
3090  * comments there for overall explanation.
3091  *
3092  * Function is called before and after parsing, so it must give same
3093  * answer each time it is called. Some subcommands are transformed
3094  * into other subcommand types, so the transform must never be made to a
3095  * lower lock level than previously assigned. All transforms are noted below.
3096  *
3097  * Since this is called before we lock the table we cannot use table metadata
3098  * to influence the type of lock we acquire.
3099  *
3100  * There should be no lockmodes hardcoded into the subcommand functions. All
3101  * lockmode decisions for ALTER TABLE are made here only. The one exception is
3102  * ALTER TABLE RENAME which is treated as a different statement type T_RenameStmt
3103  * and does not travel through this section of code and cannot be combined with
3104  * any of the subcommands given here.
3105  *
3106  * Note that Hot Standby only knows about AccessExclusiveLocks on the master
3107  * so any changes that might affect SELECTs running on standbys need to use
3108  * AccessExclusiveLocks even if you think a lesser lock would do, unless you
3109  * have a solution for that also.
3110  *
3111  * Also note that pg_dump uses only an AccessShareLock, meaning that anything
3112  * that takes a lock less than AccessExclusiveLock can change object definitions
3113  * while pg_dump is running. Be careful to check that the appropriate data is
3114  * derived by pg_dump using an MVCC snapshot, rather than syscache lookups,
3115  * otherwise we might end up with an inconsistent dump that can't restore.
3116  */
3117 LOCKMODE
3118 AlterTableGetLockLevel(List *cmds)
3119 {
3120         /*
3121          * This only works if we read catalog tables using MVCC snapshots.
3122          */
3123         ListCell   *lcmd;
3124         LOCKMODE        lockmode = ShareUpdateExclusiveLock;
3125
3126         foreach(lcmd, cmds)
3127         {
3128                 AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
3129                 LOCKMODE        cmd_lockmode = AccessExclusiveLock; /* default for compiler */
3130
3131                 switch (cmd->subtype)
3132                 {
3133                                 /*
3134                                  * These subcommands rewrite the heap, so require full locks.
3135                                  */
3136                         case AT_AddColumn:      /* may rewrite heap, in some cases and visible
3137                                                                  * to SELECT */
3138                         case AT_SetTableSpace:          /* must rewrite heap */
3139                         case AT_AlterColumnType:        /* must rewrite heap */
3140                         case AT_AddOids:        /* must rewrite heap */
3141                                 cmd_lockmode = AccessExclusiveLock;
3142                                 break;
3143
3144                                 /*
3145                                  * These subcommands may require addition of toast tables. If
3146                                  * we add a toast table to a table currently being scanned, we
3147                                  * might miss data added to the new toast table by concurrent
3148                                  * insert transactions.
3149                                  */
3150                         case AT_SetStorage:/* may add toast tables, see
3151                                                                  * ATRewriteCatalogs() */
3152                                 cmd_lockmode = AccessExclusiveLock;
3153                                 break;
3154
3155                                 /*
3156                                  * Removing constraints can affect SELECTs that have been
3157                                  * optimised assuming the constraint holds true.
3158                                  */
3159                         case AT_DropConstraint:         /* as DROP INDEX */
3160                         case AT_DropNotNull:            /* may change some SQL plans */
3161                                 cmd_lockmode = AccessExclusiveLock;
3162                                 break;
3163
3164                                 /*
3165                                  * Subcommands that may be visible to concurrent SELECTs
3166                                  */
3167                         case AT_DropColumn:     /* change visible to SELECT */
3168                         case AT_AddColumnToView:        /* CREATE VIEW */
3169                         case AT_DropOids:       /* calls AT_DropColumn */
3170                         case AT_EnableAlwaysRule:       /* may change SELECT rules */
3171                         case AT_EnableReplicaRule:      /* may change SELECT rules */
3172                         case AT_EnableRule:     /* may change SELECT rules */
3173                         case AT_DisableRule:            /* may change SELECT rules */
3174                                 cmd_lockmode = AccessExclusiveLock;
3175                                 break;
3176
3177                                 /*
3178                                  * Changing owner may remove implicit SELECT privileges
3179                                  */
3180                         case AT_ChangeOwner:            /* change visible to SELECT */
3181                                 cmd_lockmode = AccessExclusiveLock;
3182                                 break;
3183
3184                                 /*
3185                                  * Changing foreign table options may affect optimization.
3186                                  */
3187                         case AT_GenericOptions:
3188                         case AT_AlterColumnGenericOptions:
3189                                 cmd_lockmode = AccessExclusiveLock;
3190                                 break;
3191
3192                                 /*
3193                                  * These subcommands affect write operations only.
3194                                  */
3195                         case AT_EnableTrig:
3196                         case AT_EnableAlwaysTrig:
3197                         case AT_EnableReplicaTrig:
3198                         case AT_EnableTrigAll:
3199                         case AT_EnableTrigUser:
3200                         case AT_DisableTrig:
3201                         case AT_DisableTrigAll:
3202                         case AT_DisableTrigUser:
3203                                 cmd_lockmode = ShareRowExclusiveLock;
3204                                 break;
3205
3206                                 /*
3207                                  * These subcommands affect write operations only. XXX
3208                                  * Theoretically, these could be ShareRowExclusiveLock.
3209                                  */
3210                         case AT_ColumnDefault:
3211                         case AT_AlterConstraint:
3212                         case AT_AddIndex:       /* from ADD CONSTRAINT */
3213                         case AT_AddIndexConstraint:
3214                         case AT_ReplicaIdentity:
3215                         case AT_SetNotNull:
3216                         case AT_EnableRowSecurity:
3217                         case AT_DisableRowSecurity:
3218                         case AT_ForceRowSecurity:
3219                         case AT_NoForceRowSecurity:
3220                                 cmd_lockmode = AccessExclusiveLock;
3221                                 break;
3222
3223                         case AT_AddConstraint:
3224                         case AT_ProcessedConstraint:            /* becomes AT_AddConstraint */
3225                         case AT_AddConstraintRecurse:           /* becomes AT_AddConstraint */
3226                         case AT_ReAddConstraint:        /* becomes AT_AddConstraint */
3227                                 if (IsA(cmd->def, Constraint))
3228                                 {
3229                                         Constraint *con = (Constraint *) cmd->def;
3230
3231                                         switch (con->contype)
3232                                         {
3233                                                 case CONSTR_EXCLUSION:
3234                                                 case CONSTR_PRIMARY:
3235                                                 case CONSTR_UNIQUE:
3236
3237                                                         /*
3238                                                          * Cases essentially the same as CREATE INDEX. We
3239                                                          * could reduce the lock strength to ShareLock if
3240                                                          * we can work out how to allow concurrent catalog
3241                                                          * updates. XXX Might be set down to
3242                                                          * ShareRowExclusiveLock but requires further
3243                                                          * analysis.
3244                                                          */
3245                                                         cmd_lockmode = AccessExclusiveLock;
3246                                                         break;
3247                                                 case CONSTR_FOREIGN:
3248
3249                                                         /*
3250                                                          * We add triggers to both tables when we add a
3251                                                          * Foreign Key, so the lock level must be at least
3252                                                          * as strong as CREATE TRIGGER.
3253                                                          */
3254                                                         cmd_lockmode = ShareRowExclusiveLock;
3255                                                         break;
3256
3257                                                 default:
3258                                                         cmd_lockmode = AccessExclusiveLock;
3259                                         }
3260                                 }
3261                                 break;
3262
3263                                 /*
3264                                  * These subcommands affect inheritance behaviour. Queries
3265                                  * started before us will continue to see the old inheritance
3266                                  * behaviour, while queries started after we commit will see
3267                                  * new behaviour. No need to prevent reads or writes to the
3268                                  * subtable while we hook it up though. Changing the TupDesc
3269                                  * may be a problem, so keep highest lock.
3270                                  */
3271                         case AT_AddInherit:
3272                         case AT_DropInherit:
3273                                 cmd_lockmode = AccessExclusiveLock;
3274                                 break;
3275
3276                                 /*
3277                                  * These subcommands affect implicit row type conversion. They
3278                                  * have affects similar to CREATE/DROP CAST on queries. don't
3279                                  * provide for invalidating parse trees as a result of such
3280                                  * changes, so we keep these at AccessExclusiveLock.
3281                                  */
3282                         case AT_AddOf:
3283                         case AT_DropOf:
3284                                 cmd_lockmode = AccessExclusiveLock;
3285                                 break;
3286
3287                                 /*
3288                                  * Only used by CREATE OR REPLACE VIEW which must conflict
3289                                  * with an SELECTs currently using the view.
3290                                  */
3291                         case AT_ReplaceRelOptions:
3292                                 cmd_lockmode = AccessExclusiveLock;
3293                                 break;
3294
3295                                 /*
3296                                  * These subcommands affect general strategies for performance
3297                                  * and maintenance, though don't change the semantic results
3298                                  * from normal data reads and writes. Delaying an ALTER TABLE
3299                                  * behind currently active writes only delays the point where
3300                                  * the new strategy begins to take effect, so there is no
3301                                  * benefit in waiting. In this case the minimum restriction
3302                                  * applies: we don't currently allow concurrent catalog
3303                                  * updates.
3304                                  */
3305                         case AT_SetStatistics:          /* Uses MVCC in getTableAttrs() */
3306                         case AT_ClusterOn:      /* Uses MVCC in getIndexes() */
3307                         case AT_DropCluster:            /* Uses MVCC in getIndexes() */
3308                         case AT_SetOptions:     /* Uses MVCC in getTableAttrs() */
3309                         case AT_ResetOptions:           /* Uses MVCC in getTableAttrs() */
3310                                 cmd_lockmode = ShareUpdateExclusiveLock;
3311                                 break;
3312
3313                         case AT_SetLogged:
3314                         case AT_SetUnLogged:
3315                                 cmd_lockmode = AccessExclusiveLock;
3316                                 break;
3317
3318                         case AT_ValidateConstraint: /* Uses MVCC in
3319                                                                                                  * getConstraints() */
3320                                 cmd_lockmode = ShareUpdateExclusiveLock;
3321                                 break;
3322
3323                                 /*
3324                                  * Rel options are more complex than first appears. Options
3325                                  * are set here for tables, views and indexes; for historical
3326                                  * reasons these can all be used with ALTER TABLE, so we can't
3327                                  * decide between them using the basic grammar.
3328                                  */
3329                         case AT_SetRelOptions:          /* Uses MVCC in getIndexes() and
3330                                                                                  * getTables() */
3331                         case AT_ResetRelOptions:        /* Uses MVCC in getIndexes() and
3332                                                                                  * getTables() */
3333                                 cmd_lockmode = AlterTableGetRelOptionsLockLevel((List *) cmd->def);
3334                                 break;
3335
3336                         case AT_AttachPartition:
3337                         case AT_DetachPartition:
3338                                 cmd_lockmode = AccessExclusiveLock;
3339                                 break;
3340
3341                         default:                        /* oops */
3342                                 elog(ERROR, "unrecognized alter table type: %d",
3343                                          (int) cmd->subtype);
3344                                 break;
3345                 }
3346
3347                 /*
3348                  * Take the greatest lockmode from any subcommand
3349                  */
3350                 if (cmd_lockmode > lockmode)
3351                         lockmode = cmd_lockmode;
3352         }
3353
3354         return lockmode;
3355 }
3356
3357 /*
3358  * ATController provides top level control over the phases.
3359  *
3360  * parsetree is passed in to allow it to be passed to event triggers
3361  * when requested.
3362  */
3363 static void
3364 ATController(AlterTableStmt *parsetree,
3365                          Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
3366 {
3367         List       *wqueue = NIL;
3368         ListCell   *lcmd;
3369
3370         /* Phase 1: preliminary examination of commands, create work queue */
3371         foreach(lcmd, cmds)
3372         {
3373                 AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
3374
3375                 ATPrepCmd(&wqueue, rel, cmd, recurse, false, lockmode);
3376         }
3377
3378         /* Close the relation, but keep lock until commit */
3379         relation_close(rel, NoLock);
3380
3381         /* Phase 2: update system catalogs */
3382         ATRewriteCatalogs(&wqueue, lockmode);
3383
3384         /* Phase 3: scan/rewrite tables as needed */
3385         ATRewriteTables(parsetree, &wqueue, lockmode);
3386 }
3387
3388 /*
3389  * ATPrepCmd
3390  *
3391  * Traffic cop for ALTER TABLE Phase 1 operations, including simple
3392  * recursion and permission checks.
3393  *
3394  * Caller must have acquired appropriate lock type on relation already.
3395  * This lock should be held until commit.
3396  */
3397 static void
3398 ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
3399                   bool recurse, bool recursing, LOCKMODE lockmode)
3400 {
3401         AlteredTableInfo *tab;
3402         int                     pass = AT_PASS_UNSET;
3403
3404         /* Find or create work queue entry for this table */
3405         tab = ATGetQueueEntry(wqueue, rel);
3406
3407         /*
3408          * Copy the original subcommand for each table.  This avoids conflicts
3409          * when different child tables need to make different parse
3410          * transformations (for example, the same column may have different column
3411          * numbers in different children).
3412          */
3413         cmd = copyObject(cmd);
3414
3415         /*
3416          * Do permissions checking, recursion to child tables if needed, and any
3417          * additional phase-1 processing needed.
3418          */
3419         switch (cmd->subtype)
3420         {
3421                 case AT_AddColumn:              /* ADD COLUMN */
3422                         ATSimplePermissions(rel,
3423                                                  ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
3424                         ATPrepAddColumn(wqueue, rel, recurse, recursing, false, cmd,
3425                                                         lockmode);
3426                         /* Recursion occurs during execution phase */
3427                         pass = AT_PASS_ADD_COL;
3428                         break;
3429                 case AT_AddColumnToView:                /* add column via CREATE OR REPLACE
3430                                                                                  * VIEW */
3431                         ATSimplePermissions(rel, ATT_VIEW);
3432                         ATPrepAddColumn(wqueue, rel, recurse, recursing, true, cmd,
3433                                                         lockmode);
3434                         /* Recursion occurs during execution phase */
3435                         pass = AT_PASS_ADD_COL;
3436                         break;
3437                 case AT_ColumnDefault:  /* ALTER COLUMN DEFAULT */
3438
3439                         /*
3440                          * We allow defaults on views so that INSERT into a view can have
3441                          * default-ish behavior.  This works because the rewriter
3442                          * substitutes default values into INSERTs before it expands
3443                          * rules.
3444                          */
3445                         ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
3446                         ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
3447                         /* No command-specific prep needed */
3448                         pass = cmd->def ? AT_PASS_ADD_CONSTR : AT_PASS_DROP;
3449                         break;
3450                 case AT_DropNotNull:    /* ALTER COLUMN DROP NOT NULL */
3451                         ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3452                         ATPrepDropNotNull(rel, recurse, recursing);
3453                         ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
3454                         /* No command-specific prep needed */
3455                         pass = AT_PASS_DROP;
3456                         break;
3457                 case AT_SetNotNull:             /* ALTER COLUMN SET NOT NULL */
3458                         ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3459                         ATPrepSetNotNull(rel, recurse, recursing);
3460                         ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
3461                         /* No command-specific prep needed */
3462                         pass = AT_PASS_ADD_CONSTR;
3463                         break;
3464                 case AT_SetStatistics:  /* ALTER COLUMN SET STATISTICS */
3465                         ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
3466                         /* Performs own permission checks */
3467                         ATPrepSetStatistics(rel, cmd->name, cmd->def, lockmode);
3468                         pass = AT_PASS_MISC;
3469                         break;
3470                 case AT_SetOptions:             /* ALTER COLUMN SET ( options ) */
3471                 case AT_ResetOptions:   /* ALTER COLUMN RESET ( options ) */
3472                         ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_FOREIGN_TABLE);
3473                         /* This command never recurses */
3474                         pass = AT_PASS_MISC;
3475                         break;
3476                 case AT_SetStorage:             /* ALTER COLUMN SET STORAGE */
3477                         ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE);
3478                         ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
3479                         /* No command-specific prep needed */
3480                         pass = AT_PASS_MISC;
3481                         break;
3482                 case AT_DropColumn:             /* DROP COLUMN */
3483                         ATSimplePermissions(rel,
3484                                                  ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
3485                         ATPrepDropColumn(wqueue, rel, recurse, recursing, cmd, lockmode);
3486                         /* Recursion occurs during execution phase */
3487                         pass = AT_PASS_DROP;
3488                         break;
3489                 case AT_AddIndex:               /* ADD INDEX */
3490                         ATSimplePermissions(rel, ATT_TABLE);
3491                         /* This command never recurses */
3492                         /* No command-specific prep needed */
3493                         pass = AT_PASS_ADD_INDEX;
3494                         break;
3495                 case AT_AddConstraint:  /* ADD CONSTRAINT */
3496                         ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3497                         /* Recursion occurs during execution phase */
3498                         /* No command-specific prep needed except saving recurse flag */
3499                         if (recurse)
3500                                 cmd->subtype = AT_AddConstraintRecurse;
3501                         pass = AT_PASS_ADD_CONSTR;
3502                         break;
3503                 case AT_AddIndexConstraint:             /* ADD CONSTRAINT USING INDEX */
3504                         ATSimplePermissions(rel, ATT_TABLE);
3505                         /* This command never recurses */
3506                         /* No command-specific prep needed */
3507                         pass = AT_PASS_ADD_CONSTR;
3508                         break;
3509                 case AT_DropConstraint: /* DROP CONSTRAINT */
3510                         ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3511                         /* Recursion occurs during execution phase */
3512                         /* No command-specific prep needed except saving recurse flag */
3513                         if (recurse)
3514                                 cmd->subtype = AT_DropConstraintRecurse;
3515                         pass = AT_PASS_DROP;
3516                         break;
3517                 case AT_AlterColumnType:                /* ALTER COLUMN TYPE */
3518                         ATSimplePermissions(rel,
3519                                                  ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
3520                         /* Performs own recursion */
3521                         ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd, lockmode);
3522                         pass = AT_PASS_ALTER_TYPE;
3523                         break;
3524                 case AT_AlterColumnGenericOptions:
3525                         ATSimplePermissions(rel, ATT_FOREIGN_TABLE);
3526                         /* This command never recurses */
3527                         /* No command-specific prep needed */
3528                         pass = AT_PASS_MISC;
3529                         break;
3530                 case AT_ChangeOwner:    /* ALTER OWNER */
3531                         /* This command never recurses */
3532                         /* No command-specific prep needed */
3533                         pass = AT_PASS_MISC;
3534                         break;
3535                 case AT_ClusterOn:              /* CLUSTER ON */
3536                 case AT_DropCluster:    /* SET WITHOUT CLUSTER */
3537                         ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW);
3538                         /* These commands never recurse */
3539                         /* No command-specific prep needed */
3540                         pass = AT_PASS_MISC;
3541                         break;
3542                 case AT_SetLogged:              /* SET LOGGED */
3543                         ATSimplePermissions(rel, ATT_TABLE);
3544                         tab->chgPersistence = ATPrepChangePersistence(rel, true);
3545                         /* force rewrite if necessary; see comment in ATRewriteTables */
3546                         if (tab->chgPersistence)
3547                         {
3548                                 tab->rewrite |= AT_REWRITE_ALTER_PERSISTENCE;
3549                                 tab->newrelpersistence = RELPERSISTENCE_PERMANENT;
3550                         }
3551                         pass = AT_PASS_MISC;
3552                         break;
3553                 case AT_SetUnLogged:    /* SET UNLOGGED */
3554                         ATSimplePermissions(rel, ATT_TABLE);
3555                         tab->chgPersistence = ATPrepChangePersistence(rel, false);
3556                         /* force rewrite if necessary; see comment in ATRewriteTables */
3557                         if (tab->chgPersistence)
3558                         {
3559                                 tab->rewrite |= AT_REWRITE_ALTER_PERSISTENCE;
3560                                 tab->newrelpersistence = RELPERSISTENCE_UNLOGGED;
3561                         }
3562                         pass = AT_PASS_MISC;
3563                         break;
3564                 case AT_AddOids:                /* SET WITH OIDS */
3565                         ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3566                         if (!rel->rd_rel->relhasoids || recursing)
3567                                 ATPrepAddOids(wqueue, rel, recurse, cmd, lockmode);
3568                         /* Recursion occurs during execution phase */
3569                         pass = AT_PASS_ADD_COL;
3570                         break;
3571                 case AT_DropOids:               /* SET WITHOUT OIDS */
3572                         ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3573                         /* Performs own recursion */
3574                         if (rel->rd_rel->relhasoids)
3575                         {
3576                                 AlterTableCmd *dropCmd = makeNode(AlterTableCmd);
3577
3578                                 dropCmd->subtype = AT_DropColumn;
3579                                 dropCmd->name = pstrdup("oid");
3580                                 dropCmd->behavior = cmd->behavior;
3581                                 ATPrepCmd(wqueue, rel, dropCmd, recurse, false, lockmode);
3582                         }
3583                         pass = AT_PASS_DROP;
3584                         break;
3585                 case AT_SetTableSpace:  /* SET TABLESPACE */
3586                         ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX);
3587                         /* This command never recurses */
3588                         ATPrepSetTableSpace(tab, rel, cmd->name, lockmode);
3589                         pass = AT_PASS_MISC;    /* doesn't actually matter */
3590                         break;
3591                 case AT_SetRelOptions:  /* SET (...) */
3592                 case AT_ResetRelOptions:                /* RESET (...) */
3593                 case AT_ReplaceRelOptions:              /* reset them all, then set just these */
3594                         ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_MATVIEW | ATT_INDEX);
3595                         /* This command never recurses */
3596                         /* No command-specific prep needed */
3597                         pass = AT_PASS_MISC;
3598                         break;
3599                 case AT_AddInherit:             /* INHERIT */
3600                         ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3601                         /* This command never recurses */
3602                         ATPrepAddInherit(rel);
3603                         pass = AT_PASS_MISC;
3604                         break;
3605                 case AT_DropInherit:    /* NO INHERIT */
3606                         ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3607                         /* This command never recurses */
3608                         /* No command-specific prep needed */
3609                         pass = AT_PASS_MISC;
3610                         break;
3611                 case AT_AlterConstraint:                /* ALTER CONSTRAINT */
3612                         ATSimplePermissions(rel, ATT_TABLE);
3613                         pass = AT_PASS_MISC;
3614                         break;
3615                 case AT_ValidateConstraint:             /* VALIDATE CONSTRAINT */
3616                         ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3617                         /* Recursion occurs during execution phase */
3618                         /* No command-specific prep needed except saving recurse flag */
3619                         if (recurse)
3620                                 cmd->subtype = AT_ValidateConstraintRecurse;
3621                         pass = AT_PASS_MISC;
3622                         break;
3623                 case AT_ReplicaIdentity:                /* REPLICA IDENTITY ... */
3624                         ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW);
3625                         pass = AT_PASS_MISC;
3626                         /* This command never recurses */
3627                         /* No command-specific prep needed */
3628                         break;
3629                 case AT_EnableTrig:             /* ENABLE TRIGGER variants */
3630                 case AT_EnableAlwaysTrig:
3631                 case AT_EnableReplicaTrig:
3632                 case AT_EnableTrigAll:
3633                 case AT_EnableTrigUser:
3634                 case AT_DisableTrig:    /* DISABLE TRIGGER variants */
3635                 case AT_DisableTrigAll:
3636                 case AT_DisableTrigUser:
3637                         ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
3638                         pass = AT_PASS_MISC;
3639                         break;
3640                 case AT_EnableRule:             /* ENABLE/DISABLE RULE variants */
3641                 case AT_EnableAlwaysRule:
3642                 case AT_EnableReplicaRule:
3643                 case AT_DisableRule:
3644                 case AT_AddOf:                  /* OF */
3645                 case AT_DropOf: /* NOT OF */
3646                 case AT_EnableRowSecurity:
3647                 case AT_DisableRowSecurity:
3648                 case AT_ForceRowSecurity:
3649                 case AT_NoForceRowSecurity:
3650                         ATSimplePermissions(rel, ATT_TABLE);
3651                         /* These commands never recurse */
3652                         /* No command-specific prep needed */
3653                         pass = AT_PASS_MISC;
3654                         break;
3655                 case AT_GenericOptions:
3656                         ATSimplePermissions(rel, ATT_FOREIGN_TABLE);
3657                         /* No command-specific prep needed */
3658                         pass = AT_PASS_MISC;
3659                         break;
3660                 case AT_AttachPartition:
3661                 case AT_DetachPartition:
3662                         ATSimplePermissions(rel, ATT_TABLE);
3663                         /* No command-specific prep needed */
3664                         pass = AT_PASS_MISC;
3665                         break;
3666                 default:                                /* oops */
3667                         elog(ERROR, "unrecognized alter table type: %d",
3668                                  (int) cmd->subtype);
3669                         pass = AT_PASS_UNSET;           /* keep compiler quiet */
3670                         break;
3671         }
3672         Assert(pass > AT_PASS_UNSET);
3673
3674         /* Add the subcommand to the appropriate list for phase 2 */
3675         tab->subcmds[pass] = lappend(tab->subcmds[pass], cmd);
3676 }
3677
3678 /*
3679  * ATRewriteCatalogs
3680  *
3681  * Traffic cop for ALTER TABLE Phase 2 operations.  Subcommands are
3682  * dispatched in a "safe" execution order (designed to avoid unnecessary
3683  * conflicts).
3684  */
3685 static void
3686 ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode)
3687 {
3688         int                     pass;
3689         ListCell   *ltab;
3690
3691         /*
3692          * We process all the tables "in parallel", one pass at a time.  This is
3693          * needed because we may have to propagate work from one table to another
3694          * (specifically, ALTER TYPE on a foreign key's PK has to dispatch the
3695          * re-adding of the foreign key constraint to the other table).  Work can
3696          * only be propagated into later passes, however.
3697          */
3698         for (pass = 0; pass < AT_NUM_PASSES; pass++)
3699         {
3700                 /* Go through each table that needs to be processed */
3701                 foreach(ltab, *wqueue)
3702                 {
3703                         AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
3704                         List       *subcmds = tab->subcmds[pass];
3705                         Relation        rel;
3706                         ListCell   *lcmd;
3707
3708                         if (subcmds == NIL)
3709                                 continue;
3710
3711                         /*
3712                          * Appropriate lock was obtained by phase 1, needn't get it again
3713                          */
3714                         rel = relation_open(tab->relid, NoLock);
3715
3716                         foreach(lcmd, subcmds)
3717                                 ATExecCmd(wqueue, tab, rel, (AlterTableCmd *) lfirst(lcmd), lockmode);
3718
3719                         /*
3720                          * After the ALTER TYPE pass, do cleanup work (this is not done in
3721                          * ATExecAlterColumnType since it should be done only once if
3722                          * multiple columns of a table are altered).
3723                          */
3724                         if (pass == AT_PASS_ALTER_TYPE)
3725                                 ATPostAlterTypeCleanup(wqueue, tab, lockmode);
3726
3727                         relation_close(rel, NoLock);
3728                 }
3729         }
3730
3731         /* Check to see if a toast table must be added. */
3732         foreach(ltab, *wqueue)
3733         {
3734                 AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
3735
3736                 /*
3737                  * If the table is source table of ATTACH PARTITION command, we did
3738                  * not modify anything about it that will change its toasting
3739                  * requirement, so no need to check.
3740                  */
3741                 if (((tab->relkind == RELKIND_RELATION ||
3742                           tab->relkind == RELKIND_PARTITIONED_TABLE) &&
3743                          tab->partition_constraint == NIL) ||
3744                         tab->relkind == RELKIND_MATVIEW)
3745                         AlterTableCreateToastTable(tab->relid, (Datum) 0, lockmode);
3746         }
3747 }
3748
3749 /*
3750  * ATExecCmd: dispatch a subcommand to appropriate execution routine
3751  */
3752 static void
3753 ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
3754                   AlterTableCmd *cmd, LOCKMODE lockmode)
3755 {
3756         ObjectAddress address = InvalidObjectAddress;
3757
3758         switch (cmd->subtype)
3759         {
3760                 case AT_AddColumn:              /* ADD COLUMN */
3761                 case AT_AddColumnToView:                /* add column via CREATE OR REPLACE
3762                                                                                  * VIEW */
3763                         address = ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
3764                                                                           false, false, false,
3765                                                                           false, lockmode);
3766                         break;
3767                 case AT_AddColumnRecurse:
3768                         address = ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
3769                                                                           false, true, false,
3770                                                                           cmd->missing_ok, lockmode);
3771                         break;
3772                 case AT_ColumnDefault:  /* ALTER COLUMN DEFAULT */
3773                         address = ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode);
3774                         break;
3775                 case AT_DropNotNull:    /* ALTER COLUMN DROP NOT NULL */
3776                         address = ATExecDropNotNull(rel, cmd->name, lockmode);
3777                         break;
3778                 case AT_SetNotNull:             /* ALTER COLUMN SET NOT NULL */
3779                         address = ATExecSetNotNull(tab, rel, cmd->name, lockmode);
3780                         break;
3781                 case AT_SetStatistics:  /* ALTER COLUMN SET STATISTICS */
3782                         address = ATExecSetStatistics(rel, cmd->name, cmd->def, lockmode);
3783                         break;
3784                 case AT_SetOptions:             /* ALTER COLUMN SET ( options ) */
3785                         address = ATExecSetOptions(rel, cmd->name, cmd->def, false, lockmode);
3786                         break;
3787                 case AT_ResetOptions:   /* ALTER COLUMN RESET ( options ) */
3788                         address = ATExecSetOptions(rel, cmd->name, cmd->def, true, lockmode);
3789                         break;
3790                 case AT_SetStorage:             /* ALTER COLUMN SET STORAGE */
3791                         address = ATExecSetStorage(rel, cmd->name, cmd->def, lockmode);
3792                         break;
3793                 case AT_DropColumn:             /* DROP COLUMN */
3794                         address = ATExecDropColumn(wqueue, rel, cmd->name,
3795                                                                            cmd->behavior, false, false,
3796                                                                            cmd->missing_ok, lockmode);
3797                         break;
3798                 case AT_DropColumnRecurse:              /* DROP COLUMN with recursion */
3799                         address = ATExecDropColumn(wqueue, rel, cmd->name,
3800                                                                            cmd->behavior, true, false,
3801                                                                            cmd->missing_ok, lockmode);
3802                         break;
3803                 case AT_AddIndex:               /* ADD INDEX */
3804                         address = ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, false,
3805                                                                          lockmode);
3806                         break;
3807                 case AT_ReAddIndex:             /* ADD INDEX */
3808                         address = ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, true,
3809                                                                          lockmode);
3810                         break;
3811                 case AT_AddConstraint:  /* ADD CONSTRAINT */
3812                         address =
3813                                 ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
3814                                                                         false, false, lockmode);
3815                         break;
3816                 case AT_AddConstraintRecurse:   /* ADD CONSTRAINT with recursion */
3817                         address =
3818                                 ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
3819                                                                         true, false, lockmode);
3820                         break;
3821                 case AT_ReAddConstraint:                /* Re-add pre-existing check
3822                                                                                  * constraint */
3823                         address =
3824                                 ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
3825                                                                         true, true, lockmode);
3826                         break;
3827                 case AT_ReAddComment:   /* Re-add existing comment */
3828                         address = CommentObject((CommentStmt *) cmd->def);
3829                         break;
3830                 case AT_AddIndexConstraint:             /* ADD CONSTRAINT USING INDEX */
3831                         address = ATExecAddIndexConstraint(tab, rel, (IndexStmt *) cmd->def,
3832                                                                                            lockmode);
3833                         break;
3834                 case AT_AlterConstraint:                /* ALTER CONSTRAINT */
3835                         address = ATExecAlterConstraint(rel, cmd, false, false, lockmode);
3836                         break;
3837                 case AT_ValidateConstraint:             /* VALIDATE CONSTRAINT */
3838                         address = ATExecValidateConstraint(rel, cmd->name, false, false,
3839                                                                                            lockmode);
3840                         break;
3841                 case AT_ValidateConstraintRecurse:              /* VALIDATE CONSTRAINT with
3842                                                                                                  * recursion */
3843                         address = ATExecValidateConstraint(rel, cmd->name, true, false,
3844                                                                                            lockmode);
3845                         break;
3846                 case AT_DropConstraint: /* DROP CONSTRAINT */
3847                         ATExecDropConstraint(rel, cmd->name, cmd->behavior,
3848                                                                  false, false,
3849                                                                  cmd->missing_ok, lockmode);
3850                         break;
3851                 case AT_DropConstraintRecurse:  /* DROP CONSTRAINT with recursion */
3852                         ATExecDropConstraint(rel, cmd->name, cmd->behavior,
3853                                                                  true, false,
3854                                                                  cmd->missing_ok, lockmode);
3855                         break;
3856                 case AT_AlterColumnType:                /* ALTER COLUMN TYPE */
3857                         address = ATExecAlterColumnType(tab, rel, cmd, lockmode);
3858                         break;
3859                 case AT_AlterColumnGenericOptions:              /* ALTER COLUMN OPTIONS */
3860                         address =
3861                                 ATExecAlterColumnGenericOptions(rel, cmd->name,
3862                                                                                                 (List *) cmd->def, lockmode);
3863                         break;
3864                 case AT_ChangeOwner:    /* ALTER OWNER */
3865                         ATExecChangeOwner(RelationGetRelid(rel),
3866                                                           get_rolespec_oid(cmd->newowner, false),
3867                                                           false, lockmode);
3868                         break;
3869                 case AT_ClusterOn:              /* CLUSTER ON */
3870                         address = ATExecClusterOn(rel, cmd->name, lockmode);
3871                         break;
3872                 case AT_DropCluster:    /* SET WITHOUT CLUSTER */
3873                         ATExecDropCluster(rel, lockmode);
3874                         break;
3875                 case AT_SetLogged:              /* SET LOGGED */
3876                 case AT_SetUnLogged:    /* SET UNLOGGED */
3877                         break;
3878                 case AT_AddOids:                /* SET WITH OIDS */
3879                         /* Use the ADD COLUMN code, unless prep decided to do nothing */
3880                         if (cmd->def != NULL)
3881                                 address =
3882                                         ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
3883                                                                         true, false, false,
3884                                                                         cmd->missing_ok, lockmode);
3885                         break;
3886                 case AT_AddOidsRecurse: /* SET WITH OIDS */
3887                         /* Use the ADD COLUMN code, unless prep decided to do nothing */
3888                         if (cmd->def != NULL)
3889                                 address =
3890                                         ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
3891                                                                         true, true, false,
3892                                                                         cmd->missing_ok, lockmode);
3893                         break;
3894                 case AT_DropOids:               /* SET WITHOUT OIDS */
3895
3896                         /*
3897                          * Nothing to do here; we'll have generated a DropColumn
3898                          * subcommand to do the real work
3899                          */
3900                         break;
3901                 case AT_SetTableSpace:  /* SET TABLESPACE */
3902
3903                         /*
3904                          * Nothing to do here; Phase 3 does the work
3905                          */
3906                         break;
3907                 case AT_SetRelOptions:  /* SET (...) */
3908                 case AT_ResetRelOptions:                /* RESET (...) */
3909                 case AT_ReplaceRelOptions:              /* replace entire option list */
3910                         ATExecSetRelOptions(rel, (List *) cmd->def, cmd->subtype, lockmode);
3911                         break;
3912                 case AT_EnableTrig:             /* ENABLE TRIGGER name */
3913                         ATExecEnableDisableTrigger(rel, cmd->name,
3914                                                                    TRIGGER_FIRES_ON_ORIGIN, false, lockmode);
3915                         break;
3916                 case AT_EnableAlwaysTrig:               /* ENABLE ALWAYS TRIGGER name */
3917                         ATExecEnableDisableTrigger(rel, cmd->name,
3918                                                                            TRIGGER_FIRES_ALWAYS, false, lockmode);
3919                         break;
3920                 case AT_EnableReplicaTrig:              /* ENABLE REPLICA TRIGGER name */
3921                         ATExecEnableDisableTrigger(rel, cmd->name,
3922                                                                   TRIGGER_FIRES_ON_REPLICA, false, lockmode);
3923                         break;
3924                 case AT_DisableTrig:    /* DISABLE TRIGGER name */
3925                         ATExecEnableDisableTrigger(rel, cmd->name,
3926                                                                            TRIGGER_DISABLED, false, lockmode);
3927                         break;
3928                 case AT_EnableTrigAll:  /* ENABLE TRIGGER ALL */
3929                         ATExecEnableDisableTrigger(rel, NULL,
3930                                                                    TRIGGER_FIRES_ON_ORIGIN, false, lockmode);
3931                         break;
3932                 case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
3933                         ATExecEnableDisableTrigger(rel, NULL,
3934                                                                            TRIGGER_DISABLED, false, lockmode);
3935                         break;
3936                 case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
3937                         ATExecEnableDisableTrigger(rel, NULL,
3938                                                                         TRIGGER_FIRES_ON_ORIGIN, true, lockmode);
3939                         break;
3940                 case AT_DisableTrigUser:                /* DISABLE TRIGGER USER */
3941                         ATExecEnableDisableTrigger(rel, NULL,
3942                                                                            TRIGGER_DISABLED, true, lockmode);
3943                         break;
3944
3945                 case AT_EnableRule:             /* ENABLE RULE name */
3946                         ATExecEnableDisableRule(rel, cmd->name,
3947                                                                         RULE_FIRES_ON_ORIGIN, lockmode);
3948                         break;
3949                 case AT_EnableAlwaysRule:               /* ENABLE ALWAYS RULE name */
3950                         ATExecEnableDisableRule(rel, cmd->name,
3951                                                                         RULE_FIRES_ALWAYS, lockmode);
3952                         break;
3953                 case AT_EnableReplicaRule:              /* ENABLE REPLICA RULE name */
3954                         ATExecEnableDisableRule(rel, cmd->name,
3955                                                                         RULE_FIRES_ON_REPLICA, lockmode);
3956                         break;
3957                 case AT_DisableRule:    /* DISABLE RULE name */
3958                         ATExecEnableDisableRule(rel, cmd->name,
3959                                                                         RULE_DISABLED, lockmode);
3960                         break;
3961
3962                 case AT_AddInherit:
3963                         address = ATExecAddInherit(rel, (RangeVar *) cmd->def, lockmode);
3964                         break;
3965                 case AT_DropInherit:
3966                         address = ATExecDropInherit(rel, (RangeVar *) cmd->def, lockmode);
3967                         break;
3968                 case AT_AddOf:
3969                         address = ATExecAddOf(rel, (TypeName *) cmd->def, lockmode);
3970                         break;
3971                 case AT_DropOf:
3972                         ATExecDropOf(rel, lockmode);
3973                         break;
3974                 case AT_ReplicaIdentity:
3975                         ATExecReplicaIdentity(rel, (ReplicaIdentityStmt *) cmd->def, lockmode);
3976                         break;
3977                 case AT_EnableRowSecurity:
3978                         ATExecEnableRowSecurity(rel);
3979                         break;
3980                 case AT_DisableRowSecurity:
3981                         ATExecDisableRowSecurity(rel);
3982                         break;
3983                 case AT_ForceRowSecurity:
3984                         ATExecForceNoForceRowSecurity(rel, true);
3985                         break;
3986                 case AT_NoForceRowSecurity:
3987                         ATExecForceNoForceRowSecurity(rel, false);
3988                         break;
3989                 case AT_GenericOptions:
3990                         ATExecGenericOptions(rel, (List *) cmd->def);
3991                         break;
3992                 case AT_AttachPartition:
3993                         ATExecAttachPartition(wqueue, rel, (PartitionCmd *) cmd->def);
3994                         break;
3995                 case AT_DetachPartition:
3996                         ATExecDetachPartition(rel, ((PartitionCmd *) cmd->def)->name);
3997                         break;
3998                 default:                                /* oops */
3999                         elog(ERROR, "unrecognized alter table type: %d",
4000                                  (int) cmd->subtype);
4001                         break;
4002         }
4003
4004         /*
4005          * Report the subcommand to interested event triggers.
4006          */
4007         EventTriggerCollectAlterTableSubcmd((Node *) cmd, address);
4008
4009         /*
4010          * Bump the command counter to ensure the next subcommand in the sequence
4011          * can see the changes so far
4012          */
4013         CommandCounterIncrement();
4014 }
4015
4016 /*
4017  * ATRewriteTables: ALTER TABLE phase 3
4018  */
4019 static void
4020 ATRewriteTables(AlterTableStmt *parsetree, List **wqueue, LOCKMODE lockmode)
4021 {
4022         ListCell   *ltab;
4023
4024         /* Go through each table that needs to be checked or rewritten */
4025         foreach(ltab, *wqueue)
4026         {
4027                 AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
4028
4029                 /* Foreign tables have no storage, nor do partitioned tables. */
4030                 if (tab->relkind == RELKIND_FOREIGN_TABLE ||
4031                         tab->relkind == RELKIND_PARTITIONED_TABLE)
4032                         continue;
4033
4034                 /*
4035                  * If we change column data types or add/remove OIDs, the operation
4036                  * has to be propagated to tables that use this table's rowtype as a
4037                  * column type.  tab->newvals will also be non-NULL in the case where
4038                  * we're adding a column with a default.  We choose to forbid that
4039                  * case as well, since composite types might eventually support
4040                  * defaults.
4041                  *
4042                  * (Eventually we'll probably need to check for composite type
4043                  * dependencies even when we're just scanning the table without a
4044                  * rewrite, but at the moment a composite type does not enforce any
4045                  * constraints, so it's not necessary/appropriate to enforce them just
4046                  * during ALTER.)
4047                  */
4048                 if (tab->newvals != NIL || tab->rewrite > 0)
4049                 {
4050                         Relation        rel;
4051
4052                         rel = heap_open(tab->relid, NoLock);
4053                         find_composite_type_dependencies(rel->rd_rel->reltype, rel, NULL);
4054                         heap_close(rel, NoLock);
4055                 }
4056
4057                 /*
4058                  * We only need to rewrite the table if at least one column needs to
4059                  * be recomputed, we are adding/removing the OID column, or we are
4060                  * changing its persistence.
4061                  *
4062                  * There are two reasons for requiring a rewrite when changing
4063                  * persistence: on one hand, we need to ensure that the buffers
4064                  * belonging to each of the two relations are marked with or without
4065                  * BM_PERMANENT properly.  On the other hand, since rewriting creates
4066                  * and assigns a new relfilenode, we automatically create or drop an
4067                  * init fork for the relation as appropriate.
4068                  */
4069                 if (tab->rewrite > 0)
4070                 {
4071                         /* Build a temporary relation and copy data */
4072                         Relation        OldHeap;
4073                         Oid                     OIDNewHeap;
4074                         Oid                     NewTableSpace;
4075                         char            persistence;
4076
4077                         OldHeap = heap_open(tab->relid, NoLock);
4078
4079                         /*
4080                          * We don't support rewriting of system catalogs; there are too
4081                          * many corner cases and too little benefit.  In particular this
4082                          * is certainly not going to work for mapped catalogs.
4083                          */
4084                         if (IsSystemRelation(OldHeap))
4085                                 ereport(ERROR,
4086                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4087                                                  errmsg("cannot rewrite system relation \"%s\"",
4088                                                                 RelationGetRelationName(OldHeap))));
4089
4090                         if (RelationIsUsedAsCatalogTable(OldHeap))
4091                                 ereport(ERROR,
4092                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4093                                 errmsg("cannot rewrite table \"%s\" used as a catalog table",
4094                                            RelationGetRelationName(OldHeap))));
4095
4096                         /*
4097                          * Don't allow rewrite on temp tables of other backends ... their
4098                          * local buffer manager is not going to cope.
4099                          */
4100                         if (RELATION_IS_OTHER_TEMP(OldHeap))
4101                                 ereport(ERROR,
4102                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4103                                 errmsg("cannot rewrite temporary tables of other sessions")));
4104
4105                         /*
4106                          * Select destination tablespace (same as original unless user
4107                          * requested a change)
4108                          */
4109                         if (tab->newTableSpace)
4110                                 NewTableSpace = tab->newTableSpace;
4111                         else
4112                                 NewTableSpace = OldHeap->rd_rel->reltablespace;
4113
4114                         /*
4115                          * Select persistence of transient table (same as original unless
4116                          * user requested a change)
4117                          */
4118                         persistence = tab->chgPersistence ?
4119                                 tab->newrelpersistence : OldHeap->rd_rel->relpersistence;
4120
4121                         heap_close(OldHeap, NoLock);
4122
4123                         /*
4124                          * Fire off an Event Trigger now, before actually rewriting the
4125                          * table.
4126                          *
4127                          * We don't support Event Trigger for nested commands anywhere,
4128                          * here included, and parsetree is given NULL when coming from
4129                          * AlterTableInternal.
4130                          *
4131                          * And fire it only once.
4132                          */
4133                         if (parsetree)
4134                                 EventTriggerTableRewrite((Node *) parsetree,
4135                                                                                  tab->relid,
4136                                                                                  tab->rewrite);
4137
4138                         /*
4139                          * Create transient table that will receive the modified data.
4140                          *
4141                          * Ensure it is marked correctly as logged or unlogged.  We have
4142                          * to do this here so that buffers for the new relfilenode will
4143                          * have the right persistence set, and at the same time ensure
4144                          * that the original filenode's buffers will get read in with the
4145                          * correct setting (i.e. the original one).  Otherwise a rollback
4146                          * after the rewrite would possibly result with buffers for the
4147                          * original filenode having the wrong persistence setting.
4148                          *
4149                          * NB: This relies on swap_relation_files() also swapping the
4150                          * persistence. That wouldn't work for pg_class, but that can't be
4151                          * unlogged anyway.
4152                          */
4153                         OIDNewHeap = make_new_heap(tab->relid, NewTableSpace, persistence,
4154                                                                            lockmode);
4155
4156                         /*
4157                          * Copy the heap data into the new table with the desired
4158                          * modifications, and test the current data within the table
4159                          * against new constraints generated by ALTER TABLE commands.
4160                          */
4161                         ATRewriteTable(tab, OIDNewHeap, lockmode);
4162
4163                         /*
4164                          * Swap the physical files of the old and new heaps, then rebuild
4165                          * indexes and discard the old heap.  We can use RecentXmin for
4166                          * the table's new relfrozenxid because we rewrote all the tuples
4167                          * in ATRewriteTable, so no older Xid remains in the table.  Also,
4168                          * we never try to swap toast tables by content, since we have no
4169                          * interest in letting this code work on system catalogs.
4170                          */
4171                         finish_heap_swap(tab->relid, OIDNewHeap,
4172                                                          false, false, true,
4173                                                          !OidIsValid(tab->newTableSpace),
4174                                                          RecentXmin,
4175                                                          ReadNextMultiXactId(),
4176                                                          persistence);
4177                 }
4178                 else
4179                 {
4180                         /*
4181                          * Test the current data within the table against new constraints
4182                          * generated by ALTER TABLE commands, but don't rebuild data.
4183                          */
4184                         if (tab->constraints != NIL || tab->new_notnull ||
4185                                 tab->partition_constraint != NIL)
4186                                 ATRewriteTable(tab, InvalidOid, lockmode);
4187
4188                         /*
4189                          * If we had SET TABLESPACE but no reason to reconstruct tuples,
4190                          * just do a block-by-block copy.
4191                          */
4192                         if (tab->newTableSpace)
4193                                 ATExecSetTableSpace(tab->relid, tab->newTableSpace, lockmode);
4194                 }
4195         }
4196
4197         /*
4198          * Foreign key constraints are checked in a final pass, since (a) it's
4199          * generally best to examine each one separately, and (b) it's at least
4200          * theoretically possible that we have changed both relations of the
4201          * foreign key, and we'd better have finished both rewrites before we try
4202          * to read the tables.
4203          */
4204         foreach(ltab, *wqueue)
4205         {
4206                 AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
4207                 Relation        rel = NULL;
4208                 ListCell   *lcon;
4209
4210                 foreach(lcon, tab->constraints)
4211                 {
4212                         NewConstraint *con = lfirst(lcon);
4213
4214                         if (con->contype == CONSTR_FOREIGN)
4215                         {
4216                                 Constraint *fkconstraint = (Constraint *) con->qual;
4217                                 Relation        refrel;
4218
4219                                 if (rel == NULL)
4220                                 {
4221                                         /* Long since locked, no need for another */
4222                                         rel = heap_open(tab->relid, NoLock);
4223                                 }
4224
4225                                 refrel = heap_open(con->refrelid, RowShareLock);
4226
4227                                 validateForeignKeyConstraint(fkconstraint->conname, rel, refrel,
4228                                                                                          con->refindid,
4229                                                                                          con->conid);
4230
4231                                 /*
4232                                  * No need to mark the constraint row as validated, we did
4233                                  * that when we inserted the row earlier.
4234                                  */
4235
4236                                 heap_close(refrel, NoLock);
4237                         }
4238                 }
4239
4240                 if (rel)
4241                         heap_close(rel, NoLock);
4242         }
4243 }
4244
4245 /*
4246  * ATRewriteTable: scan or rewrite one table
4247  *
4248  * OIDNewHeap is InvalidOid if we don't need to rewrite
4249  */
4250 static void
4251 ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
4252 {
4253         Relation        oldrel;
4254         Relation        newrel;
4255         TupleDesc       oldTupDesc;
4256         TupleDesc       newTupDesc;
4257         bool            needscan = false;
4258         List       *notnull_attrs;
4259         int                     i;
4260         ListCell   *l;
4261         EState     *estate;
4262         CommandId       mycid;
4263         BulkInsertState bistate;
4264         int                     hi_options;
4265         List       *partqualstate = NIL;
4266
4267         /*
4268          * Open the relation(s).  We have surely already locked the existing
4269          * table.
4270          */
4271         oldrel = heap_open(tab->relid, NoLock);
4272         oldTupDesc = tab->oldDesc;
4273         newTupDesc = RelationGetDescr(oldrel);          /* includes all mods */
4274
4275         if (OidIsValid(OIDNewHeap))
4276                 newrel = heap_open(OIDNewHeap, lockmode);
4277         else
4278                 newrel = NULL;
4279
4280         /*
4281          * Prepare a BulkInsertState and options for heap_insert. Because we're
4282          * building a new heap, we can skip WAL-logging and fsync it to disk at
4283          * the end instead (unless WAL-logging is required for archiving or
4284          * streaming replication). The FSM is empty too, so don't bother using it.
4285          */
4286         if (newrel)
4287         {
4288                 mycid = GetCurrentCommandId(true);
4289                 bistate = GetBulkInsertState();
4290
4291                 hi_options = HEAP_INSERT_SKIP_FSM;
4292                 if (!XLogIsNeeded())
4293                         hi_options |= HEAP_INSERT_SKIP_WAL;
4294         }
4295         else
4296         {
4297                 /* keep compiler quiet about using these uninitialized */
4298                 mycid = 0;
4299                 bistate = NULL;
4300                 hi_options = 0;
4301         }
4302
4303         /*
4304          * Generate the constraint and default execution states
4305          */
4306
4307         estate = CreateExecutorState();
4308
4309         /* Build the needed expression execution states */
4310         foreach(l, tab->constraints)
4311         {
4312                 NewConstraint *con = lfirst(l);
4313
4314                 switch (con->contype)
4315                 {
4316                         case CONSTR_CHECK:
4317                                 needscan = true;
4318                                 con->qualstate = (List *)
4319                                         ExecPrepareExpr((Expr *) con->qual, estate);
4320                                 break;
4321                         case CONSTR_FOREIGN:
4322                                 /* Nothing to do here */
4323                                 break;
4324                         default:
4325                                 elog(ERROR, "unrecognized constraint type: %d",
4326                                          (int) con->contype);
4327                 }
4328         }
4329
4330         /* Build expression execution states for partition check quals */
4331         if (tab->partition_constraint)
4332         {
4333                 needscan = true;
4334                 partqualstate = (List *)
4335                         ExecPrepareExpr((Expr *) tab->partition_constraint,
4336                                                         estate);
4337         }
4338
4339         foreach(l, tab->newvals)
4340         {
4341                 NewColumnValue *ex = lfirst(l);
4342
4343                 /* expr already planned */
4344                 ex->exprstate = ExecInitExpr((Expr *) ex->expr, NULL);
4345         }
4346
4347         notnull_attrs = NIL;
4348         if (newrel || tab->new_notnull)
4349         {
4350                 /*
4351                  * If we are rebuilding the tuples OR if we added any new NOT NULL
4352                  * constraints, check all not-null constraints.  This is a bit of
4353                  * overkill but it minimizes risk of bugs, and heap_attisnull is a
4354                  * pretty cheap test anyway.
4355                  */
4356                 for (i = 0; i < newTupDesc->natts; i++)
4357                 {
4358                         if (newTupDesc->attrs[i]->attnotnull &&
4359                                 !newTupDesc->attrs[i]->attisdropped)
4360                                 notnull_attrs = lappend_int(notnull_attrs, i);
4361                 }
4362                 if (notnull_attrs)
4363                         needscan = true;
4364         }
4365
4366         if (newrel || needscan)
4367         {
4368                 ExprContext *econtext;
4369                 Datum      *values;
4370                 bool       *isnull;
4371                 TupleTableSlot *oldslot;
4372                 TupleTableSlot *newslot;
4373                 HeapScanDesc scan;
4374                 HeapTuple       tuple;
4375                 MemoryContext oldCxt;
4376                 List       *dropped_attrs = NIL;
4377                 ListCell   *lc;
4378                 Snapshot        snapshot;
4379
4380                 if (newrel)
4381                         ereport(DEBUG1,
4382                                         (errmsg("rewriting table \"%s\"",
4383                                                         RelationGetRelationName(oldrel))));
4384                 else
4385                         ereport(DEBUG1,
4386                                         (errmsg("verifying table \"%s\"",
4387                                                         RelationGetRelationName(oldrel))));
4388
4389                 if (newrel)
4390                 {
4391                         /*
4392                          * All predicate locks on the tuples or pages are about to be made
4393                          * invalid, because we move tuples around.  Promote them to
4394                          * relation locks.
4395                          */
4396                         TransferPredicateLocksToHeapRelation(oldrel);
4397                 }
4398
4399                 econtext = GetPerTupleExprContext(estate);
4400
4401                 /*
4402                  * Make tuple slots for old and new tuples.  Note that even when the
4403                  * tuples are the same, the tupDescs might not be (consider ADD COLUMN
4404                  * without a default).
4405                  */
4406                 oldslot = MakeSingleTupleTableSlot(oldTupDesc);
4407                 newslot = MakeSingleTupleTableSlot(newTupDesc);
4408
4409                 /* Preallocate values/isnull arrays */
4410                 i = Max(newTupDesc->natts, oldTupDesc->natts);
4411                 values = (Datum *) palloc(i * sizeof(Datum));
4412                 isnull = (bool *) palloc(i * sizeof(bool));
4413                 memset(values, 0, i * sizeof(Datum));
4414                 memset(isnull, true, i * sizeof(bool));
4415
4416                 /*
4417                  * Any attributes that are dropped according to the new tuple
4418                  * descriptor can be set to NULL. We precompute the list of dropped
4419                  * attributes to avoid needing to do so in the per-tuple loop.
4420                  */
4421                 for (i = 0; i < newTupDesc->natts; i++)
4422                 {
4423                         if (newTupDesc->attrs[i]->attisdropped)
4424                                 dropped_attrs = lappend_int(dropped_attrs, i);
4425                 }
4426
4427                 /*
4428                  * Scan through the rows, generating a new row if needed and then
4429                  * checking all the constraints.
4430                  */
4431                 snapshot = RegisterSnapshot(GetLatestSnapshot());
4432                 scan = heap_beginscan(oldrel, snapshot, 0, NULL);
4433
4434                 /*
4435                  * Switch to per-tuple memory context and reset it for each tuple
4436                  * produced, so we don't leak memory.
4437                  */
4438                 oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
4439
4440                 while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
4441                 {
4442                         if (tab->rewrite > 0)
4443                         {
4444                                 Oid                     tupOid = InvalidOid;
4445
4446                                 /* Extract data from old tuple */
4447                                 heap_deform_tuple(tuple, oldTupDesc, values, isnull);
4448                                 if (oldTupDesc->tdhasoid)
4449                                         tupOid = HeapTupleGetOid(tuple);
4450
4451                                 /* Set dropped attributes to null in new tuple */
4452                                 foreach(lc, dropped_attrs)
4453                                         isnull[lfirst_int(lc)] = true;
4454
4455                                 /*
4456                                  * Process supplied expressions to replace selected columns.
4457                                  * Expression inputs come from the old tuple.
4458                                  */
4459                                 ExecStoreTuple(tuple, oldslot, InvalidBuffer, false);
4460                                 econtext->ecxt_scantuple = oldslot;
4461
4462                                 foreach(l, tab->newvals)
4463                                 {
4464                                         NewColumnValue *ex = lfirst(l);
4465
4466                                         values[ex->attnum - 1] = ExecEvalExpr(ex->exprstate,
4467                                                                                                                   econtext,
4468                                                                                                          &isnull[ex->attnum - 1]);
4469                                 }
4470
4471                                 /*
4472                                  * Form the new tuple. Note that we don't explicitly pfree it,
4473                                  * since the per-tuple memory context will be reset shortly.
4474                                  */
4475                                 tuple = heap_form_tuple(newTupDesc, values, isnull);
4476
4477                                 /* Preserve OID, if any */
4478                                 if (newTupDesc->tdhasoid)
4479                                         HeapTupleSetOid(tuple, tupOid);
4480
4481                                 /*
4482                                  * Constraints might reference the tableoid column, so
4483                                  * initialize t_tableOid before evaluating them.
4484                                  */
4485                                 tuple->t_tableOid = RelationGetRelid(oldrel);
4486                         }
4487
4488                         /* Now check any constraints on the possibly-changed tuple */
4489                         ExecStoreTuple(tuple, newslot, InvalidBuffer, false);
4490                         econtext->ecxt_scantuple = newslot;
4491
4492                         foreach(l, notnull_attrs)
4493                         {
4494                                 int                     attn = lfirst_int(l);
4495
4496                                 if (heap_attisnull(tuple, attn + 1))
4497                                         ereport(ERROR,
4498                                                         (errcode(ERRCODE_NOT_NULL_VIOLATION),
4499                                                          errmsg("column \"%s\" contains null values",
4500                                                                   NameStr(newTupDesc->attrs[attn]->attname)),
4501                                                          errtablecol(oldrel, attn + 1)));
4502                         }
4503
4504                         foreach(l, tab->constraints)
4505                         {
4506                                 NewConstraint *con = lfirst(l);
4507
4508                                 switch (con->contype)
4509                                 {
4510                                         case CONSTR_CHECK:
4511                                                 if (!ExecQual(con->qualstate, econtext, true))
4512                                                         ereport(ERROR,
4513                                                                         (errcode(ERRCODE_CHECK_VIOLATION),
4514                                                                          errmsg("check constraint \"%s\" is violated by some row",
4515                                                                                         con->name),
4516                                                                          errtableconstraint(oldrel, con->name)));
4517                                                 break;
4518                                         case CONSTR_FOREIGN:
4519                                                 /* Nothing to do here */
4520                                                 break;
4521                                         default:
4522                                                 elog(ERROR, "unrecognized constraint type: %d",
4523                                                          (int) con->contype);
4524                                 }
4525                         }
4526
4527                         if (partqualstate && !ExecQual(partqualstate, econtext, true))
4528                                 ereport(ERROR,
4529                                                 (errcode(ERRCODE_CHECK_VIOLATION),
4530                                         errmsg("partition constraint is violated by some row")));
4531
4532                         /* Write the tuple out to the new relation */
4533                         if (newrel)
4534                                 heap_insert(newrel, tuple, mycid, hi_options, bistate);
4535
4536                         ResetExprContext(econtext);
4537
4538                         CHECK_FOR_INTERRUPTS();
4539                 }
4540
4541                 MemoryContextSwitchTo(oldCxt);
4542                 heap_endscan(scan);
4543                 UnregisterSnapshot(snapshot);
4544
4545                 ExecDropSingleTupleTableSlot(oldslot);
4546                 ExecDropSingleTupleTableSlot(newslot);
4547         }
4548
4549         FreeExecutorState(estate);
4550
4551         heap_close(oldrel, NoLock);
4552         if (newrel)
4553         {
4554                 FreeBulkInsertState(bistate);
4555
4556                 /* If we skipped writing WAL, then we need to sync the heap. */
4557                 if (hi_options & HEAP_INSERT_SKIP_WAL)
4558                         heap_sync(newrel);
4559
4560                 heap_close(newrel, NoLock);
4561         }
4562 }
4563
4564 /*
4565  * ATGetQueueEntry: find or create an entry in the ALTER TABLE work queue
4566  */
4567 static AlteredTableInfo *
4568 ATGetQueueEntry(List **wqueue, Relation rel)
4569 {
4570         Oid                     relid = RelationGetRelid(rel);
4571         AlteredTableInfo *tab;
4572         ListCell   *ltab;
4573
4574         foreach(ltab, *wqueue)
4575         {
4576                 tab = (AlteredTableInfo *) lfirst(ltab);
4577                 if (tab->relid == relid)
4578                         return tab;
4579         }
4580
4581         /*
4582          * Not there, so add it.  Note that we make a copy of the relation's
4583          * existing descriptor before anything interesting can happen to it.
4584          */
4585         tab = (AlteredTableInfo *) palloc0(sizeof(AlteredTableInfo));
4586         tab->relid = relid;
4587         tab->relkind = rel->rd_rel->relkind;
4588         tab->oldDesc = CreateTupleDescCopy(RelationGetDescr(rel));
4589         tab->newrelpersistence = RELPERSISTENCE_PERMANENT;
4590         tab->chgPersistence = false;
4591
4592         *wqueue = lappend(*wqueue, tab);
4593
4594         return tab;
4595 }
4596
4597 /*
4598  * ATSimplePermissions
4599  *
4600  * - Ensure that it is a relation (or possibly a view)
4601  * - Ensure this user is the owner
4602  * - Ensure that it is not a system table
4603  */
4604 static void
4605 ATSimplePermissions(Relation rel, int allowed_targets)
4606 {
4607         int                     actual_target;
4608
4609         switch (rel->rd_rel->relkind)
4610         {
4611                 case RELKIND_RELATION:
4612                 case RELKIND_PARTITIONED_TABLE:
4613                         actual_target = ATT_TABLE;
4614                         break;
4615                 case RELKIND_VIEW:
4616                         actual_target = ATT_VIEW;
4617                         break;
4618                 case RELKIND_MATVIEW:
4619                         actual_target = ATT_MATVIEW;
4620                         break;
4621                 case RELKIND_INDEX:
4622                         actual_target = ATT_INDEX;
4623                         break;
4624                 case RELKIND_COMPOSITE_TYPE:
4625                         actual_target = ATT_COMPOSITE_TYPE;
4626                         break;
4627                 case RELKIND_FOREIGN_TABLE:
4628                         actual_target = ATT_FOREIGN_TABLE;
4629                         break;
4630                 default:
4631                         actual_target = 0;
4632                         break;
4633         }
4634
4635         /* Wrong target type? */
4636         if ((actual_target & allowed_targets) == 0)
4637                 ATWrongRelkindError(rel, allowed_targets);
4638
4639         /* Permissions checks */
4640         if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
4641                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
4642                                            RelationGetRelationName(rel));
4643
4644         if (!allowSystemTableMods && IsSystemRelation(rel))
4645                 ereport(ERROR,
4646                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4647                                  errmsg("permission denied: \"%s\" is a system catalog",
4648                                                 RelationGetRelationName(rel))));
4649 }
4650
4651 /*
4652  * ATWrongRelkindError
4653  *
4654  * Throw an error when a relation has been determined to be of the wrong
4655  * type.
4656  */
4657 static void
4658 ATWrongRelkindError(Relation rel, int allowed_targets)
4659 {
4660         char       *msg;
4661
4662         switch (allowed_targets)
4663         {
4664                 case ATT_TABLE:
4665                         msg = _("\"%s\" is not a table");
4666                         break;
4667                 case ATT_TABLE | ATT_VIEW:
4668                         msg = _("\"%s\" is not a table or view");
4669                         break;
4670                 case ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE:
4671                         msg = _("\"%s\" is not a table, view, or foreign table");
4672                         break;
4673                 case ATT_TABLE | ATT_VIEW | ATT_MATVIEW | ATT_INDEX:
4674                         msg = _("\"%s\" is not a table, view, materialized view, or index");
4675                         break;
4676                 case ATT_TABLE | ATT_MATVIEW:
4677                         msg = _("\"%s\" is not a table or materialized view");
4678                         break;
4679                 case ATT_TABLE | ATT_MATVIEW | ATT_INDEX:
4680                         msg = _("\"%s\" is not a table, materialized view, or index");
4681                         break;
4682                 case ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE:
4683                         msg = _("\"%s\" is not a table, materialized view, or foreign table");
4684                         break;
4685                 case ATT_TABLE | ATT_FOREIGN_TABLE:
4686                         msg = _("\"%s\" is not a table or foreign table");
4687                         break;
4688                 case ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE:
4689                         msg = _("\"%s\" is not a table, composite type, or foreign table");
4690                         break;
4691                 case ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_FOREIGN_TABLE:
4692                         msg = _("\"%s\" is not a table, materialized view, index, or foreign table");
4693                         break;
4694                 case ATT_VIEW:
4695                         msg = _("\"%s\" is not a view");
4696                         break;
4697                 case ATT_FOREIGN_TABLE:
4698                         msg = _("\"%s\" is not a foreign table");
4699                         break;
4700                 default:
4701                         /* shouldn't get here, add all necessary cases above */
4702                         msg = _("\"%s\" is of the wrong type");
4703                         break;
4704         }
4705
4706         ereport(ERROR,
4707                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4708                          errmsg(msg, RelationGetRelationName(rel))));
4709 }
4710
4711 /*
4712  * ATSimpleRecursion
4713  *
4714  * Simple table recursion sufficient for most ALTER TABLE operations.
4715  * All direct and indirect children are processed in an unspecified order.
4716  * Note that if a child inherits from the original table via multiple
4717  * inheritance paths, it will be visited just once.
4718  */
4719 static void
4720 ATSimpleRecursion(List **wqueue, Relation rel,
4721                                   AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode)
4722 {
4723         /*
4724          * Propagate to children if desired.  Only plain tables and foreign tables
4725          * have children, so no need to search for other relkinds.
4726          */
4727         if (recurse &&
4728                 (rel->rd_rel->relkind == RELKIND_RELATION ||
4729                  rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
4730                  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
4731         {
4732                 Oid                     relid = RelationGetRelid(rel);
4733                 ListCell   *child;
4734                 List       *children;
4735
4736                 children = find_all_inheritors(relid, lockmode, NULL);
4737
4738                 /*
4739                  * find_all_inheritors does the recursive search of the inheritance
4740                  * hierarchy, so all we have to do is process all of the relids in the
4741                  * list that it returns.
4742                  */
4743                 foreach(child, children)
4744                 {
4745                         Oid                     childrelid = lfirst_oid(child);
4746                         Relation        childrel;
4747
4748                         if (childrelid == relid)
4749                                 continue;
4750                         /* find_all_inheritors already got lock */
4751                         childrel = relation_open(childrelid, NoLock);
4752                         CheckTableNotInUse(childrel, "ALTER TABLE");
4753                         ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode);
4754                         relation_close(childrel, NoLock);
4755                 }
4756         }
4757 }
4758
4759 /*
4760  * ATTypedTableRecursion
4761  *
4762  * Propagate ALTER TYPE operations to the typed tables of that type.
4763  * Also check the RESTRICT/CASCADE behavior.  Given CASCADE, also permit
4764  * recursion to inheritance children of the typed tables.
4765  */
4766 static void
4767 ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
4768                                           LOCKMODE lockmode)
4769 {
4770         ListCell   *child;
4771         List       *children;
4772
4773         Assert(rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
4774
4775         children = find_typed_table_dependencies(rel->rd_rel->reltype,
4776                                                                                          RelationGetRelationName(rel),
4777                                                                                          cmd->behavior);
4778
4779         foreach(child, children)
4780         {
4781                 Oid                     childrelid = lfirst_oid(child);
4782                 Relation        childrel;
4783
4784                 childrel = relation_open(childrelid, lockmode);
4785                 CheckTableNotInUse(childrel, "ALTER TABLE");
4786                 ATPrepCmd(wqueue, childrel, cmd, true, true, lockmode);
4787                 relation_close(childrel, NoLock);
4788         }
4789 }
4790
4791
4792 /*
4793  * find_composite_type_dependencies
4794  *
4795  * Check to see if a composite type is being used as a column in some
4796  * other table (possibly nested several levels deep in composite types!).
4797  * Eventually, we'd like to propagate the check or rewrite operation
4798  * into other such tables, but for now, just error out if we find any.
4799  *
4800  * Caller should provide either a table name or a type name (not both) to
4801  * report in the error message, if any.
4802  *
4803  * We assume that functions and views depending on the type are not reasons
4804  * to reject the ALTER.  (How safe is this really?)
4805  */
4806 void
4807 find_composite_type_dependencies(Oid typeOid, Relation origRelation,
4808                                                                  const char *origTypeName)
4809 {
4810         Relation        depRel;
4811         ScanKeyData key[2];
4812         SysScanDesc depScan;
4813         HeapTuple       depTup;
4814         Oid                     arrayOid;
4815
4816         /*
4817          * We scan pg_depend to find those things that depend on the rowtype. (We
4818          * assume we can ignore refobjsubid for a rowtype.)
4819          */
4820         depRel = heap_open(DependRelationId, AccessShareLock);
4821
4822         ScanKeyInit(&key[0],
4823                                 Anum_pg_depend_refclassid,
4824                                 BTEqualStrategyNumber, F_OIDEQ,
4825                                 ObjectIdGetDatum(TypeRelationId));
4826         ScanKeyInit(&key[1],
4827                                 Anum_pg_depend_refobjid,
4828                                 BTEqualStrategyNumber, F_OIDEQ,
4829                                 ObjectIdGetDatum(typeOid));
4830
4831         depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
4832                                                                  NULL, 2, key);
4833
4834         while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
4835         {
4836                 Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
4837                 Relation        rel;
4838                 Form_pg_attribute att;
4839
4840                 /* Ignore dependees that aren't user columns of relations */
4841                 /* (we assume system columns are never of rowtypes) */
4842                 if (pg_depend->classid != RelationRelationId ||
4843                         pg_depend->objsubid <= 0)
4844                         continue;
4845
4846                 rel = relation_open(pg_depend->objid, AccessShareLock);
4847                 att = rel->rd_att->attrs[pg_depend->objsubid - 1];
4848
4849                 if (rel->rd_rel->relkind == RELKIND_RELATION ||
4850                         rel->rd_rel->relkind == RELKIND_MATVIEW ||
4851                         rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
4852                 {
4853                         if (origTypeName)
4854                                 ereport(ERROR,
4855                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4856                                                  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4857                                                                 origTypeName,
4858                                                                 RelationGetRelationName(rel),
4859                                                                 NameStr(att->attname))));
4860                         else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
4861                                 ereport(ERROR,
4862                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4863                                                  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4864                                                                 RelationGetRelationName(origRelation),
4865                                                                 RelationGetRelationName(rel),
4866                                                                 NameStr(att->attname))));
4867                         else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4868                                 ereport(ERROR,
4869                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4870                                                  errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
4871                                                                 RelationGetRelationName(origRelation),
4872                                                                 RelationGetRelationName(rel),
4873                                                                 NameStr(att->attname))));
4874                         else
4875                                 ereport(ERROR,
4876                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4877                                                  errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
4878                                                                 RelationGetRelationName(origRelation),
4879                                                                 RelationGetRelationName(rel),
4880                                                                 NameStr(att->attname))));
4881                 }
4882                 else if (OidIsValid(rel->rd_rel->reltype))
4883                 {
4884                         /*
4885                          * A view or composite type itself isn't a problem, but we must
4886                          * recursively check for indirect dependencies via its rowtype.
4887                          */
4888                         find_composite_type_dependencies(rel->rd_rel->reltype,
4889                                                                                          origRelation, origTypeName);
4890                 }
4891
4892                 relation_close(rel, AccessShareLock);
4893         }
4894
4895         systable_endscan(depScan);
4896
4897         relation_close(depRel, AccessShareLock);
4898
4899         /*
4900          * If there's an array type for the rowtype, must check for uses of it,
4901          * too.
4902          */
4903         arrayOid = get_array_type(typeOid);
4904         if (OidIsValid(arrayOid))
4905                 find_composite_type_dependencies(arrayOid, origRelation, origTypeName);
4906 }
4907
4908
4909 /*
4910  * find_typed_table_dependencies
4911  *
4912  * Check to see if a composite type is being used as the type of a
4913  * typed table.  Abort if any are found and behavior is RESTRICT.
4914  * Else return the list of tables.
4915  */
4916 static List *
4917 find_typed_table_dependencies(Oid typeOid, const char *typeName, DropBehavior behavior)
4918 {
4919         Relation        classRel;
4920         ScanKeyData key[1];
4921         HeapScanDesc scan;
4922         HeapTuple       tuple;
4923         List       *result = NIL;
4924
4925         classRel = heap_open(RelationRelationId, AccessShareLock);
4926
4927         ScanKeyInit(&key[0],
4928                                 Anum_pg_class_reloftype,
4929                                 BTEqualStrategyNumber, F_OIDEQ,
4930                                 ObjectIdGetDatum(typeOid));
4931
4932         scan = heap_beginscan_catalog(classRel, 1, key);
4933
4934         while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
4935         {
4936                 if (behavior == DROP_RESTRICT)
4937                         ereport(ERROR,
4938                                         (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
4939                                          errmsg("cannot alter type \"%s\" because it is the type of a typed table",
4940                                                         typeName),
4941                         errhint("Use ALTER ... CASCADE to alter the typed tables too.")));
4942                 else
4943                         result = lappend_oid(result, HeapTupleGetOid(tuple));
4944         }
4945
4946         heap_endscan(scan);
4947         heap_close(classRel, AccessShareLock);
4948
4949         return result;
4950 }
4951
4952
4953 /*
4954  * check_of_type
4955  *
4956  * Check whether a type is suitable for CREATE TABLE OF/ALTER TABLE OF.  If it
4957  * isn't suitable, throw an error.  Currently, we require that the type
4958  * originated with CREATE TYPE AS.  We could support any row type, but doing so
4959  * would require handling a number of extra corner cases in the DDL commands.
4960  */
4961 void
4962 check_of_type(HeapTuple typetuple)
4963 {
4964         Form_pg_type typ = (Form_pg_type) GETSTRUCT(typetuple);
4965         bool            typeOk = false;
4966
4967         if (typ->typtype == TYPTYPE_COMPOSITE)
4968         {
4969                 Relation        typeRelation;
4970
4971                 Assert(OidIsValid(typ->typrelid));
4972                 typeRelation = relation_open(typ->typrelid, AccessShareLock);
4973                 typeOk = (typeRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
4974
4975                 /*
4976                  * Close the parent rel, but keep our AccessShareLock on it until xact
4977                  * commit.  That will prevent someone else from deleting or ALTERing
4978                  * the type before the typed table creation/conversion commits.
4979                  */
4980                 relation_close(typeRelation, NoLock);
4981         }
4982         if (!typeOk)
4983                 ereport(ERROR,
4984                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4985                                  errmsg("type %s is not a composite type",
4986                                                 format_type_be(HeapTupleGetOid(typetuple)))));
4987 }
4988
4989
4990 /*
4991  * ALTER TABLE ADD COLUMN
4992  *
4993  * Adds an additional attribute to a relation making the assumption that
4994  * CHECK, NOT NULL, and FOREIGN KEY constraints will be removed from the
4995  * AT_AddColumn AlterTableCmd by parse_utilcmd.c and added as independent
4996  * AlterTableCmd's.
4997  *
4998  * ADD COLUMN cannot use the normal ALTER TABLE recursion mechanism, because we
4999  * have to decide at runtime whether to recurse or not depending on whether we
5000  * actually add a column or merely merge with an existing column.  (We can't
5001  * check this in a static pre-pass because it won't handle multiple inheritance
5002  * situations correctly.)
5003  */
5004 static void
5005 ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
5006                                 bool is_view, AlterTableCmd *cmd, LOCKMODE lockmode)
5007 {
5008         if (rel->rd_rel->reloftype && !recursing)
5009                 ereport(ERROR,
5010                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5011                                  errmsg("cannot add column to typed table")));
5012
5013         if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
5014                 ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
5015
5016         if (recurse && !is_view)
5017                 cmd->subtype = AT_AddColumnRecurse;
5018 }
5019
5020 /*
5021  * Add a column to a table; this handles the AT_AddOids cases as well.  The
5022  * return value is the address of the new column in the parent relation.
5023  */
5024 static ObjectAddress
5025 ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
5026                                 ColumnDef *colDef, bool isOid,
5027                                 bool recurse, bool recursing,
5028                                 bool if_not_exists, LOCKMODE lockmode)
5029 {
5030         Oid                     myrelid = RelationGetRelid(rel);
5031         Relation        pgclass,
5032                                 attrdesc;
5033         HeapTuple       reltup;
5034         FormData_pg_attribute attribute;
5035         int                     newattnum;
5036         char            relkind;
5037         HeapTuple       typeTuple;
5038         Oid                     typeOid;
5039         int32           typmod;
5040         Oid                     collOid;
5041         Form_pg_type tform;
5042         Expr       *defval;
5043         List       *children;
5044         ListCell   *child;
5045         AclResult       aclresult;
5046         ObjectAddress address;
5047
5048         /* At top level, permission check was done in ATPrepCmd, else do it */
5049         if (recursing)
5050                 ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
5051
5052         if (rel->rd_rel->relispartition && !recursing)
5053                 ereport(ERROR,
5054                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5055                                  errmsg("cannot add column to a partition")));
5056
5057         attrdesc = heap_open(AttributeRelationId, RowExclusiveLock);
5058
5059         /*
5060          * Are we adding the column to a recursion child?  If so, check whether to
5061          * merge with an existing definition for the column.  If we do merge, we
5062          * must not recurse.  Children will already have the column, and recursing
5063          * into them would mess up attinhcount.
5064          */
5065         if (colDef->inhcount > 0)
5066         {
5067                 HeapTuple       tuple;
5068
5069                 /* Does child already have a column by this name? */
5070                 tuple = SearchSysCacheCopyAttName(myrelid, colDef->colname);
5071                 if (HeapTupleIsValid(tuple))
5072                 {
5073                         Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
5074                         Oid                     ctypeId;
5075                         int32           ctypmod;
5076                         Oid                     ccollid;
5077
5078                         /* Child column must match on type, typmod, and collation */
5079                         typenameTypeIdAndMod(NULL, colDef->typeName, &ctypeId, &ctypmod);
5080                         if (ctypeId != childatt->atttypid ||
5081                                 ctypmod != childatt->atttypmod)
5082                                 ereport(ERROR,
5083                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
5084                                                  errmsg("child table \"%s\" has different type for column \"%s\"",
5085                                                         RelationGetRelationName(rel), colDef->colname)));
5086                         ccollid = GetColumnDefCollation(NULL, colDef, ctypeId);
5087                         if (ccollid != childatt->attcollation)
5088                                 ereport(ERROR,
5089                                                 (errcode(ERRCODE_COLLATION_MISMATCH),
5090                                                  errmsg("child table \"%s\" has different collation for column \"%s\"",
5091                                                           RelationGetRelationName(rel), colDef->colname),
5092                                                  errdetail("\"%s\" versus \"%s\"",
5093                                                                    get_collation_name(ccollid),
5094                                                            get_collation_name(childatt->attcollation))));
5095
5096                         /* If it's OID, child column must actually be OID */
5097                         if (isOid && childatt->attnum != ObjectIdAttributeNumber)
5098                                 ereport(ERROR,
5099                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
5100                                  errmsg("child table \"%s\" has a conflicting \"%s\" column",
5101                                                 RelationGetRelationName(rel), colDef->colname)));
5102
5103                         /* Bump the existing child att's inhcount */
5104                         childatt->attinhcount++;
5105                         CatalogTupleUpdate(attrdesc, &tuple->t_self, tuple);
5106
5107                         heap_freetuple(tuple);
5108
5109                         /* Inform the user about the merge */
5110                         ereport(NOTICE,
5111                           (errmsg("merging definition of column \"%s\" for child \"%s\"",
5112                                           colDef->colname, RelationGetRelationName(rel))));
5113
5114                         heap_close(attrdesc, RowExclusiveLock);
5115                         return InvalidObjectAddress;
5116                 }
5117         }
5118
5119         pgclass = heap_open(RelationRelationId, RowExclusiveLock);
5120
5121         reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
5122         if (!HeapTupleIsValid(reltup))
5123                 elog(ERROR, "cache lookup failed for relation %u", myrelid);
5124         relkind = ((Form_pg_class) GETSTRUCT(reltup))->relkind;
5125
5126         /* skip if the name already exists and if_not_exists is true */
5127         if (!check_for_column_name_collision(rel, colDef->colname, if_not_exists))
5128         {
5129                 heap_close(attrdesc, RowExclusiveLock);
5130                 heap_freetuple(reltup);
5131                 heap_close(pgclass, RowExclusiveLock);
5132                 return InvalidObjectAddress;
5133         }
5134
5135         /* Determine the new attribute's number */
5136         if (isOid)
5137                 newattnum = ObjectIdAttributeNumber;
5138         else
5139         {
5140                 newattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts + 1;
5141                 if (newattnum > MaxHeapAttributeNumber)
5142                         ereport(ERROR,
5143                                         (errcode(ERRCODE_TOO_MANY_COLUMNS),
5144                                          errmsg("tables can have at most %d columns",
5145                                                         MaxHeapAttributeNumber)));
5146         }
5147
5148         typeTuple = typenameType(NULL, colDef->typeName, &typmod);
5149         tform = (Form_pg_type) GETSTRUCT(typeTuple);
5150         typeOid = HeapTupleGetOid(typeTuple);
5151
5152         aclresult = pg_type_aclcheck(typeOid, GetUserId(), ACL_USAGE);
5153         if (aclresult != ACLCHECK_OK)
5154                 aclcheck_error_type(aclresult, typeOid);
5155
5156         collOid = GetColumnDefCollation(NULL, colDef, typeOid);
5157
5158         /* make sure datatype is legal for a column */
5159         CheckAttributeType(colDef->colname, typeOid, collOid,
5160                                            list_make1_oid(rel->rd_rel->reltype),
5161                                            false);
5162
5163         /* construct new attribute's pg_attribute entry */
5164         attribute.attrelid = myrelid;
5165         namestrcpy(&(attribute.attname), colDef->colname);
5166         attribute.atttypid = typeOid;
5167         attribute.attstattarget = (newattnum > 0) ? -1 : 0;
5168         attribute.attlen = tform->typlen;
5169         attribute.attcacheoff = -1;
5170         attribute.atttypmod = typmod;
5171         attribute.attnum = newattnum;
5172         attribute.attbyval = tform->typbyval;
5173         attribute.attndims = list_length(colDef->typeName->arrayBounds);
5174         attribute.attstorage = tform->typstorage;
5175         attribute.attalign = tform->typalign;
5176         attribute.attnotnull = colDef->is_not_null;
5177         attribute.atthasdef = false;
5178         attribute.attisdropped = false;
5179         attribute.attislocal = colDef->is_local;
5180         attribute.attinhcount = colDef->inhcount;
5181         attribute.attcollation = collOid;
5182         /* attribute.attacl is handled by InsertPgAttributeTuple */
5183
5184         ReleaseSysCache(typeTuple);
5185
5186         InsertPgAttributeTuple(attrdesc, &attribute, NULL);
5187
5188         heap_close(attrdesc, RowExclusiveLock);
5189
5190         /*
5191          * Update pg_class tuple as appropriate
5192          */
5193         if (isOid)
5194                 ((Form_pg_class) GETSTRUCT(reltup))->relhasoids = true;
5195         else
5196                 ((Form_pg_class) GETSTRUCT(reltup))->relnatts = newattnum;
5197
5198         CatalogTupleUpdate(pgclass, &reltup->t_self, reltup);
5199
5200         heap_freetuple(reltup);
5201
5202         /* Post creation hook for new attribute */
5203         InvokeObjectPostCreateHook(RelationRelationId, myrelid, newattnum);
5204
5205         heap_close(pgclass, RowExclusiveLock);
5206
5207         /* Make the attribute's catalog entry visible */
5208         CommandCounterIncrement();
5209
5210         /*
5211          * Store the DEFAULT, if any, in the catalogs
5212          */
5213         if (colDef->raw_default)
5214         {
5215                 RawColumnDefault *rawEnt;
5216
5217                 rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
5218                 rawEnt->attnum = attribute.attnum;
5219                 rawEnt->raw_default = copyObject(colDef->raw_default);
5220
5221                 /*
5222                  * This function is intended for CREATE TABLE, so it processes a
5223                  * _list_ of defaults, but we just do one.
5224                  */
5225                 AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
5226                                                                   false, true, false);
5227
5228                 /* Make the additional catalog changes visible */
5229                 CommandCounterIncrement();
5230         }
5231
5232         /*
5233          * Tell Phase 3 to fill in the default expression, if there is one.
5234          *
5235          * If there is no default, Phase 3 doesn't have to do anything, because
5236          * that effectively means that the default is NULL.  The heap tuple access
5237          * routines always check for attnum > # of attributes in tuple, and return
5238          * NULL if so, so without any modification of the tuple data we will get
5239          * the effect of NULL values in the new column.
5240          *
5241          * An exception occurs when the new column is of a domain type: the domain
5242          * might have a NOT NULL constraint, or a check constraint that indirectly
5243          * rejects nulls.  If there are any domain constraints then we construct
5244          * an explicit NULL default value that will be passed through
5245          * CoerceToDomain processing.  (This is a tad inefficient, since it causes
5246          * rewriting the table which we really don't have to do, but the present
5247          * design of domain processing doesn't offer any simple way of checking
5248          * the constraints more directly.)
5249          *
5250          * Note: we use build_column_default, and not just the cooked default
5251          * returned by AddRelationNewConstraints, so that the right thing happens
5252          * when a datatype's default applies.
5253          *
5254          * We skip this step completely for views and foreign tables.  For a view,
5255          * we can only get here from CREATE OR REPLACE VIEW, which historically
5256          * doesn't set up defaults, not even for domain-typed columns.  And in any
5257          * case we mustn't invoke Phase 3 on a view or foreign table, since they
5258          * have no storage.
5259          */
5260         if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE
5261                 && relkind != RELKIND_FOREIGN_TABLE && attribute.attnum > 0)
5262         {
5263                 defval = (Expr *) build_column_default(rel, attribute.attnum);
5264
5265                 if (!defval && DomainHasConstraints(typeOid))
5266                 {
5267                         Oid                     baseTypeId;
5268                         int32           baseTypeMod;
5269                         Oid                     baseTypeColl;
5270
5271                         baseTypeMod = typmod;
5272                         baseTypeId = getBaseTypeAndTypmod(typeOid, &baseTypeMod);
5273                         baseTypeColl = get_typcollation(baseTypeId);
5274                         defval = (Expr *) makeNullConst(baseTypeId, baseTypeMod, baseTypeColl);
5275                         defval = (Expr *) coerce_to_target_type(NULL,
5276                                                                                                         (Node *) defval,
5277                                                                                                         baseTypeId,
5278                                                                                                         typeOid,
5279                                                                                                         typmod,
5280                                                                                                         COERCION_ASSIGNMENT,
5281                                                                                                         COERCE_IMPLICIT_CAST,
5282                                                                                                         -1);
5283                         if (defval == NULL) /* should not happen */
5284                                 elog(ERROR, "failed to coerce base type to domain");
5285                 }
5286
5287                 if (defval)
5288                 {
5289                         NewColumnValue *newval;
5290
5291                         newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
5292                         newval->attnum = attribute.attnum;
5293                         newval->expr = expression_planner(defval);
5294
5295                         tab->newvals = lappend(tab->newvals, newval);
5296                         tab->rewrite |= AT_REWRITE_DEFAULT_VAL;
5297                 }
5298
5299                 /*
5300                  * If the new column is NOT NULL, tell Phase 3 it needs to test that.
5301                  * (Note we don't do this for an OID column.  OID will be marked not
5302                  * null, but since it's filled specially, there's no need to test
5303                  * anything.)
5304                  */
5305                 tab->new_notnull |= colDef->is_not_null;
5306         }
5307
5308         /*
5309          * If we are adding an OID column, we have to tell Phase 3 to rewrite the
5310          * table to fix that.
5311          */
5312         if (isOid)
5313                 tab->rewrite |= AT_REWRITE_ALTER_OID;
5314
5315         /*
5316          * Add needed dependency entries for the new column.
5317          */
5318         add_column_datatype_dependency(myrelid, newattnum, attribute.atttypid);
5319         add_column_collation_dependency(myrelid, newattnum, attribute.attcollation);
5320
5321         /*
5322          * Propagate to children as appropriate.  Unlike most other ALTER
5323          * routines, we have to do this one level of recursion at a time; we can't
5324          * use find_all_inheritors to do it in one pass.
5325          */
5326         children = find_inheritance_children(RelationGetRelid(rel), lockmode);
5327
5328         /*
5329          * If we are told not to recurse, there had better not be any child
5330          * tables; else the addition would put them out of step.
5331          */
5332         if (children && !recurse)
5333                 ereport(ERROR,
5334                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5335                                  errmsg("column must be added to child tables too")));
5336
5337         /* Children should see column as singly inherited */
5338         if (!recursing)
5339         {
5340                 colDef = copyObject(colDef);
5341                 colDef->inhcount = 1;
5342                 colDef->is_local = false;
5343         }
5344
5345         foreach(child, children)
5346         {
5347                 Oid                     childrelid = lfirst_oid(child);
5348                 Relation        childrel;
5349                 AlteredTableInfo *childtab;
5350
5351                 /* find_inheritance_children already got lock */
5352                 childrel = heap_open(childrelid, NoLock);
5353                 CheckTableNotInUse(childrel, "ALTER TABLE");
5354
5355                 /* Find or create work queue entry for this table */
5356                 childtab = ATGetQueueEntry(wqueue, childrel);
5357
5358                 /* Recurse to child; return value is ignored */
5359                 ATExecAddColumn(wqueue, childtab, childrel,
5360                                                 colDef, isOid, recurse, true,
5361                                                 if_not_exists, lockmode);
5362
5363                 heap_close(childrel, NoLock);
5364         }
5365
5366         ObjectAddressSubSet(address, RelationRelationId, myrelid, newattnum);
5367         return address;
5368 }
5369
5370 /*
5371  * If a new or renamed column will collide with the name of an existing
5372  * column and if_not_exists is false then error out, else do nothing.
5373  */
5374 static bool
5375 check_for_column_name_collision(Relation rel, const char *colname,
5376                                                                 bool if_not_exists)
5377 {
5378         HeapTuple       attTuple;
5379         int                     attnum;
5380
5381         /*
5382          * this test is deliberately not attisdropped-aware, since if one tries to
5383          * add a column matching a dropped column name, it's gonna fail anyway.
5384          */
5385         attTuple = SearchSysCache2(ATTNAME,
5386                                                            ObjectIdGetDatum(RelationGetRelid(rel)),
5387                                                            PointerGetDatum(colname));
5388         if (!HeapTupleIsValid(attTuple))
5389                 return true;
5390
5391         attnum = ((Form_pg_attribute) GETSTRUCT(attTuple))->attnum;
5392         ReleaseSysCache(attTuple);
5393
5394         /*
5395          * We throw a different error message for conflicts with system column
5396          * names, since they are normally not shown and the user might otherwise
5397          * be confused about the reason for the conflict.
5398          */
5399         if (attnum <= 0)
5400                 ereport(ERROR,
5401                                 (errcode(ERRCODE_DUPLICATE_COLUMN),
5402                          errmsg("column name \"%s\" conflicts with a system column name",
5403                                         colname)));
5404         else
5405         {
5406                 if (if_not_exists)
5407                 {
5408                         ereport(NOTICE,
5409                                         (errcode(ERRCODE_DUPLICATE_COLUMN),
5410                                          errmsg("column \"%s\" of relation \"%s\" already exists, skipping",
5411                                                         colname, RelationGetRelationName(rel))));
5412                         return false;
5413                 }
5414
5415                 ereport(ERROR,
5416                                 (errcode(ERRCODE_DUPLICATE_COLUMN),
5417                                  errmsg("column \"%s\" of relation \"%s\" already exists",
5418                                                 colname, RelationGetRelationName(rel))));
5419         }
5420
5421         return true;
5422 }
5423
5424 /*
5425  * Install a column's dependency on its datatype.
5426  */
5427 static void
5428 add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid)
5429 {
5430         ObjectAddress myself,
5431                                 referenced;
5432
5433         myself.classId = RelationRelationId;
5434         myself.objectId = relid;
5435         myself.objectSubId = attnum;
5436         referenced.classId = TypeRelationId;
5437         referenced.objectId = typid;
5438         referenced.objectSubId = 0;
5439         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
5440 }
5441
5442 /*
5443  * Install a column's dependency on its collation.
5444  */
5445 static void
5446 add_column_collation_dependency(Oid relid, int32 attnum, Oid collid)
5447 {
5448         ObjectAddress myself,
5449                                 referenced;
5450
5451         /* We know the default collation is pinned, so don't bother recording it */
5452         if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
5453         {
5454                 myself.classId = RelationRelationId;
5455                 myself.objectId = relid;
5456                 myself.objectSubId = attnum;
5457                 referenced.classId = CollationRelationId;
5458                 referenced.objectId = collid;
5459                 referenced.objectSubId = 0;
5460                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
5461         }
5462 }
5463
5464 /*
5465  * ALTER TABLE SET WITH OIDS
5466  *
5467  * Basically this is an ADD COLUMN for the special OID column.  We have
5468  * to cons up a ColumnDef node because the ADD COLUMN code needs one.
5469  */
5470 static void
5471 ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOCKMODE lockmode)
5472 {
5473         /* If we're recursing to a child table, the ColumnDef is already set up */
5474         if (cmd->def == NULL)
5475         {
5476                 ColumnDef  *cdef = makeNode(ColumnDef);
5477
5478                 cdef->colname = pstrdup("oid");
5479                 cdef->typeName = makeTypeNameFromOid(OIDOID, -1);
5480                 cdef->inhcount = 0;
5481                 cdef->is_local = true;
5482                 cdef->is_not_null = true;
5483                 cdef->storage = 0;
5484                 cdef->location = -1;
5485                 cmd->def = (Node *) cdef;
5486         }
5487         ATPrepAddColumn(wqueue, rel, recurse, false, false, cmd, lockmode);
5488
5489         if (recurse)
5490                 cmd->subtype = AT_AddOidsRecurse;
5491 }
5492
5493 /*
5494  * ALTER TABLE ALTER COLUMN DROP NOT NULL
5495  *
5496  * Return the address of the modified column.  If the column was already
5497  * nullable, InvalidObjectAddress is returned.
5498  */
5499
5500 static void
5501 ATPrepDropNotNull(Relation rel, bool recurse, bool recursing)
5502 {
5503         /*
5504          * If the parent is a partitioned table, like check constraints, NOT NULL
5505          * constraints must be dropped from child tables.
5506          */
5507         if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
5508                 !recurse && !recursing)
5509                 ereport(ERROR,
5510                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5511                                  errmsg("constraint must be dropped from child tables too")));
5512 }
5513 static ObjectAddress
5514 ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
5515 {
5516         HeapTuple       tuple;
5517         AttrNumber      attnum;
5518         Relation        attr_rel;
5519         List       *indexoidlist;
5520         ListCell   *indexoidscan;
5521         ObjectAddress address;
5522
5523         /*
5524          * lookup the attribute
5525          */
5526         attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
5527
5528         tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
5529
5530         if (!HeapTupleIsValid(tuple))
5531                 ereport(ERROR,
5532                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5533                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5534                                                 colName, RelationGetRelationName(rel))));
5535
5536         attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
5537
5538         /* Prevent them from altering a system attribute */
5539         if (attnum <= 0)
5540                 ereport(ERROR,
5541                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5542                                  errmsg("cannot alter system column \"%s\"",
5543                                                 colName)));
5544
5545         /*
5546          * Check that the attribute is not in a primary key
5547          *
5548          * Note: we'll throw error even if the pkey index is not valid.
5549          */
5550
5551         /* Loop over all indexes on the relation */
5552         indexoidlist = RelationGetIndexList(rel);
5553
5554         foreach(indexoidscan, indexoidlist)
5555         {
5556                 Oid                     indexoid = lfirst_oid(indexoidscan);
5557                 HeapTuple       indexTuple;
5558                 Form_pg_index indexStruct;
5559                 int                     i;
5560
5561                 indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
5562                 if (!HeapTupleIsValid(indexTuple))
5563                         elog(ERROR, "cache lookup failed for index %u", indexoid);
5564                 indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
5565
5566                 /* If the index is not a primary key, skip the check */
5567                 if (indexStruct->indisprimary)
5568                 {
5569                         /*
5570                          * Loop over each attribute in the primary key and see if it
5571                          * matches the to-be-altered attribute
5572                          */
5573                         for (i = 0; i < indexStruct->indnatts; i++)
5574                         {
5575                                 if (indexStruct->indkey.values[i] == attnum)
5576                                         ereport(ERROR,
5577                                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5578                                                          errmsg("column \"%s\" is in a primary key",
5579                                                                         colName)));
5580                         }
5581                 }
5582
5583                 ReleaseSysCache(indexTuple);
5584         }
5585
5586         list_free(indexoidlist);
5587
5588         /* If rel is partition, shouldn't drop NOT NULL if parent has the same */
5589         if (rel->rd_rel->relispartition)
5590         {
5591                 Oid                     parentId = get_partition_parent(RelationGetRelid(rel));
5592                 Relation        parent = heap_open(parentId, AccessShareLock);
5593                 TupleDesc       tupDesc = RelationGetDescr(parent);
5594                 AttrNumber      parent_attnum;
5595
5596                 parent_attnum = get_attnum(parentId, colName);
5597                 if (tupDesc->attrs[parent_attnum - 1]->attnotnull)
5598                         ereport(ERROR,
5599                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5600                                    errmsg("column \"%s\" is marked NOT NULL in parent table",
5601                                                   colName)));
5602                 heap_close(parent, AccessShareLock);
5603         }
5604
5605         /*
5606          * If the table is a range partitioned table, check that the column is not
5607          * in the partition key.
5608          */
5609         if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
5610         {
5611                 PartitionKey key = RelationGetPartitionKey(rel);
5612
5613                 if (get_partition_strategy(key) == PARTITION_STRATEGY_RANGE)
5614                 {
5615                         int                     partnatts = get_partition_natts(key),
5616                                                 i;
5617
5618                         for (i = 0; i < partnatts; i++)
5619                         {
5620                                 AttrNumber      partattnum = get_partition_col_attnum(key, i);
5621
5622                                 if (partattnum == attnum)
5623                                         ereport(ERROR,
5624                                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5625                                                          errmsg("column \"%s\" is in range partition key",
5626                                                                         colName)));
5627                         }
5628                 }
5629         }
5630
5631         /*
5632          * Okay, actually perform the catalog change ... if needed
5633          */
5634         if (((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull)
5635         {
5636                 ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = FALSE;
5637
5638                 CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
5639
5640                 ObjectAddressSubSet(address, RelationRelationId,
5641                                                         RelationGetRelid(rel), attnum);
5642         }
5643         else
5644                 address = InvalidObjectAddress;
5645
5646         InvokeObjectPostAlterHook(RelationRelationId,
5647                                                           RelationGetRelid(rel), attnum);
5648
5649         heap_close(attr_rel, RowExclusiveLock);
5650
5651         return address;
5652 }
5653
5654 /*
5655  * ALTER TABLE ALTER COLUMN SET NOT NULL
5656  *
5657  * Return the address of the modified column.  If the column was already NOT
5658  * NULL, InvalidObjectAddress is returned.
5659  */
5660
5661 static void
5662 ATPrepSetNotNull(Relation rel, bool recurse, bool recursing)
5663 {
5664         /*
5665          * If the parent is a partitioned table, like check constraints, NOT NULL
5666          * constraints must be added to the child tables.
5667          */
5668         if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
5669                 !recurse && !recursing)
5670                 ereport(ERROR,
5671                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5672                                  errmsg("constraint must be added to child tables too")));
5673 }
5674
5675 static ObjectAddress
5676 ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
5677                                  const char *colName, LOCKMODE lockmode)
5678 {
5679         HeapTuple       tuple;
5680         AttrNumber      attnum;
5681         Relation        attr_rel;
5682         ObjectAddress address;
5683
5684         /*
5685          * lookup the attribute
5686          */
5687         attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
5688
5689         tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
5690
5691         if (!HeapTupleIsValid(tuple))
5692                 ereport(ERROR,
5693                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5694                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5695                                                 colName, RelationGetRelationName(rel))));
5696
5697         attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
5698
5699         /* Prevent them from altering a system attribute */
5700         if (attnum <= 0)
5701                 ereport(ERROR,
5702                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5703                                  errmsg("cannot alter system column \"%s\"",
5704                                                 colName)));
5705
5706         /*
5707          * Okay, actually perform the catalog change ... if needed
5708          */
5709         if (!((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull)
5710         {
5711                 ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = TRUE;
5712
5713                 CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
5714
5715                 /* Tell Phase 3 it needs to test the constraint */
5716                 tab->new_notnull = true;
5717
5718                 ObjectAddressSubSet(address, RelationRelationId,
5719                                                         RelationGetRelid(rel), attnum);
5720         }
5721         else
5722                 address = InvalidObjectAddress;
5723
5724         InvokeObjectPostAlterHook(RelationRelationId,
5725                                                           RelationGetRelid(rel), attnum);
5726
5727         heap_close(attr_rel, RowExclusiveLock);
5728
5729         return address;
5730 }
5731
5732 /*
5733  * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT
5734  *
5735  * Return the address of the affected column.
5736  */
5737 static ObjectAddress
5738 ATExecColumnDefault(Relation rel, const char *colName,
5739                                         Node *newDefault, LOCKMODE lockmode)
5740 {
5741         AttrNumber      attnum;
5742         ObjectAddress address;
5743
5744         /*
5745          * get the number of the attribute
5746          */
5747         attnum = get_attnum(RelationGetRelid(rel), colName);
5748         if (attnum == InvalidAttrNumber)
5749                 ereport(ERROR,
5750                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5751                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5752                                                 colName, RelationGetRelationName(rel))));
5753
5754         /* Prevent them from altering a system attribute */
5755         if (attnum <= 0)
5756                 ereport(ERROR,
5757                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5758                                  errmsg("cannot alter system column \"%s\"",
5759                                                 colName)));
5760
5761         /*
5762          * Remove any old default for the column.  We use RESTRICT here for
5763          * safety, but at present we do not expect anything to depend on the
5764          * default.
5765          *
5766          * We treat removing the existing default as an internal operation when it
5767          * is preparatory to adding a new default, but as a user-initiated
5768          * operation when the user asked for a drop.
5769          */
5770         RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false,
5771                                           newDefault == NULL ? false : true);
5772
5773         if (newDefault)
5774         {
5775                 /* SET DEFAULT */
5776                 RawColumnDefault *rawEnt;
5777
5778                 rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
5779                 rawEnt->attnum = attnum;
5780                 rawEnt->raw_default = newDefault;
5781
5782                 /*
5783                  * This function is intended for CREATE TABLE, so it processes a
5784                  * _list_ of defaults, but we just do one.
5785                  */
5786                 AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
5787                                                                   false, true, false);
5788         }
5789
5790         ObjectAddressSubSet(address, RelationRelationId,
5791                                                 RelationGetRelid(rel), attnum);
5792         return address;
5793 }
5794
5795 /*
5796  * ALTER TABLE ALTER COLUMN SET STATISTICS
5797  */
5798 static void
5799 ATPrepSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
5800 {
5801         /*
5802          * We do our own permission checking because (a) we want to allow SET
5803          * STATISTICS on indexes (for expressional index columns), and (b) we want
5804          * to allow SET STATISTICS on system catalogs without requiring
5805          * allowSystemTableMods to be turned on.
5806          */
5807         if (rel->rd_rel->relkind != RELKIND_RELATION &&
5808                 rel->rd_rel->relkind != RELKIND_MATVIEW &&
5809                 rel->rd_rel->relkind != RELKIND_INDEX &&
5810                 rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
5811                 rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
5812                 ereport(ERROR,
5813                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5814                                  errmsg("\"%s\" is not a table, materialized view, index, or foreign table",
5815                                                 RelationGetRelationName(rel))));
5816
5817         /* Permissions checks */
5818         if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
5819                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
5820                                            RelationGetRelationName(rel));
5821 }
5822
5823 /*
5824  * Return value is the address of the modified column
5825  */
5826 static ObjectAddress
5827 ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
5828 {
5829         int                     newtarget;
5830         Relation        attrelation;
5831         HeapTuple       tuple;
5832         Form_pg_attribute attrtuple;
5833         AttrNumber      attnum;
5834         ObjectAddress address;
5835
5836         Assert(IsA(newValue, Integer));
5837         newtarget = intVal(newValue);
5838
5839         /*
5840          * Limit target to a sane range
5841          */
5842         if (newtarget < -1)
5843         {
5844                 ereport(ERROR,
5845                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5846                                  errmsg("statistics target %d is too low",
5847                                                 newtarget)));
5848         }
5849         else if (newtarget > 10000)
5850         {
5851                 newtarget = 10000;
5852                 ereport(WARNING,
5853                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5854                                  errmsg("lowering statistics target to %d",
5855                                                 newtarget)));
5856         }
5857
5858         attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
5859
5860         tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
5861
5862         if (!HeapTupleIsValid(tuple))
5863                 ereport(ERROR,
5864                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5865                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5866                                                 colName, RelationGetRelationName(rel))));
5867         attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
5868
5869         attnum = attrtuple->attnum;
5870         if (attnum <= 0)
5871                 ereport(ERROR,
5872                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5873                                  errmsg("cannot alter system column \"%s\"",
5874                                                 colName)));
5875
5876         attrtuple->attstattarget = newtarget;
5877
5878         CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
5879
5880         InvokeObjectPostAlterHook(RelationRelationId,
5881                                                           RelationGetRelid(rel),
5882                                                           attrtuple->attnum);
5883         ObjectAddressSubSet(address, RelationRelationId,
5884                                                 RelationGetRelid(rel), attnum);
5885         heap_freetuple(tuple);
5886
5887         heap_close(attrelation, RowExclusiveLock);
5888
5889         return address;
5890 }
5891
5892 /*
5893  * Return value is the address of the modified column
5894  */
5895 static ObjectAddress
5896 ATExecSetOptions(Relation rel, const char *colName, Node *options,
5897                                  bool isReset, LOCKMODE lockmode)
5898 {
5899         Relation        attrelation;
5900         HeapTuple       tuple,
5901                                 newtuple;
5902         Form_pg_attribute attrtuple;
5903         AttrNumber      attnum;
5904         Datum           datum,
5905                                 newOptions;
5906         bool            isnull;
5907         ObjectAddress address;
5908         Datum           repl_val[Natts_pg_attribute];
5909         bool            repl_null[Natts_pg_attribute];
5910         bool            repl_repl[Natts_pg_attribute];
5911
5912         attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
5913
5914         tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
5915
5916         if (!HeapTupleIsValid(tuple))
5917                 ereport(ERROR,
5918                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5919                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5920                                                 colName, RelationGetRelationName(rel))));
5921         attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
5922
5923         attnum = attrtuple->attnum;
5924         if (attnum <= 0)
5925                 ereport(ERROR,
5926                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5927                                  errmsg("cannot alter system column \"%s\"",
5928                                                 colName)));
5929
5930         /* Generate new proposed attoptions (text array) */
5931         datum = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
5932                                                         &isnull);
5933         newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
5934                                                                          castNode(List, options), NULL, NULL,
5935                                                                          false, isReset);
5936         /* Validate new options */
5937         (void) attribute_reloptions(newOptions, true);
5938
5939         /* Build new tuple. */
5940         memset(repl_null, false, sizeof(repl_null));
5941         memset(repl_repl, false, sizeof(repl_repl));
5942         if (newOptions != (Datum) 0)
5943                 repl_val[Anum_pg_attribute_attoptions - 1] = newOptions;
5944         else
5945                 repl_null[Anum_pg_attribute_attoptions - 1] = true;
5946         repl_repl[Anum_pg_attribute_attoptions - 1] = true;
5947         newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation),
5948                                                                  repl_val, repl_null, repl_repl);
5949
5950         /* Update system catalog. */
5951         CatalogTupleUpdate(attrelation, &newtuple->t_self, newtuple);
5952
5953         InvokeObjectPostAlterHook(RelationRelationId,
5954                                                           RelationGetRelid(rel),
5955                                                           attrtuple->attnum);
5956         ObjectAddressSubSet(address, RelationRelationId,
5957                                                 RelationGetRelid(rel), attnum);
5958
5959         heap_freetuple(newtuple);
5960
5961         ReleaseSysCache(tuple);
5962
5963         heap_close(attrelation, RowExclusiveLock);
5964
5965         return address;
5966 }
5967
5968 /*
5969  * ALTER TABLE ALTER COLUMN SET STORAGE
5970  *
5971  * Return value is the address of the modified column
5972  */
5973 static ObjectAddress
5974 ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
5975 {
5976         char       *storagemode;
5977         char            newstorage;
5978         Relation        attrelation;
5979         HeapTuple       tuple;
5980         Form_pg_attribute attrtuple;
5981         AttrNumber      attnum;
5982         ObjectAddress address;
5983
5984         Assert(IsA(newValue, String));
5985         storagemode = strVal(newValue);
5986
5987         if (pg_strcasecmp(storagemode, "plain") == 0)
5988                 newstorage = 'p';
5989         else if (pg_strcasecmp(storagemode, "external") == 0)
5990                 newstorage = 'e';
5991         else if (pg_strcasecmp(storagemode, "extended") == 0)
5992                 newstorage = 'x';
5993         else if (pg_strcasecmp(storagemode, "main") == 0)
5994                 newstorage = 'm';
5995         else
5996         {
5997                 ereport(ERROR,
5998                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5999                                  errmsg("invalid storage type \"%s\"",
6000                                                 storagemode)));
6001                 newstorage = 0;                 /* keep compiler quiet */
6002         }
6003
6004         attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
6005
6006         tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
6007
6008         if (!HeapTupleIsValid(tuple))
6009                 ereport(ERROR,
6010                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
6011                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
6012                                                 colName, RelationGetRelationName(rel))));
6013         attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
6014
6015         attnum = attrtuple->attnum;
6016         if (attnum <= 0)
6017                 ereport(ERROR,
6018                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6019                                  errmsg("cannot alter system column \"%s\"",
6020                                                 colName)));
6021
6022         /*
6023          * safety check: do not allow toasted storage modes unless column datatype
6024          * is TOAST-aware.
6025          */
6026         if (newstorage == 'p' || TypeIsToastable(attrtuple->atttypid))
6027                 attrtuple->attstorage = newstorage;
6028         else
6029                 ereport(ERROR,
6030                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6031                                  errmsg("column data type %s can only have storage PLAIN",
6032                                                 format_type_be(attrtuple->atttypid))));
6033
6034         CatalogTupleUpdate(attrelation, &tuple->t_self, tuple);
6035
6036         InvokeObjectPostAlterHook(RelationRelationId,
6037                                                           RelationGetRelid(rel),
6038                                                           attrtuple->attnum);
6039
6040         heap_freetuple(tuple);
6041
6042         heap_close(attrelation, RowExclusiveLock);
6043
6044         ObjectAddressSubSet(address, RelationRelationId,
6045                                                 RelationGetRelid(rel), attnum);
6046         return address;
6047 }
6048
6049
6050 /*
6051  * ALTER TABLE DROP COLUMN
6052  *
6053  * DROP COLUMN cannot use the normal ALTER TABLE recursion mechanism,
6054  * because we have to decide at runtime whether to recurse or not depending
6055  * on whether attinhcount goes to zero or not.  (We can't check this in a
6056  * static pre-pass because it won't handle multiple inheritance situations
6057  * correctly.)
6058  */
6059 static void
6060 ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
6061                                  AlterTableCmd *cmd, LOCKMODE lockmode)
6062 {
6063         if (rel->rd_rel->reloftype && !recursing)
6064                 ereport(ERROR,
6065                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
6066                                  errmsg("cannot drop column from typed table")));
6067
6068         if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
6069                 ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
6070
6071         if (recurse)
6072                 cmd->subtype = AT_DropColumnRecurse;
6073 }
6074
6075 /*
6076  * Checks if attnum is a partition attribute for rel
6077  *
6078  * Sets *used_in_expr if attnum is found to be referenced in some partition
6079  * key expression.  It's possible for a column to be both used directly and
6080  * as part of an expression; if that happens, *used_in_expr may end up as
6081  * either true or false.  That's OK for current uses of this function, because
6082  * *used_in_expr is only used to tailor the error message text.
6083  */
6084 static bool
6085 is_partition_attr(Relation rel, AttrNumber attnum, bool *used_in_expr)
6086 {
6087         PartitionKey key;
6088         int                     partnatts;
6089         List       *partexprs;
6090         ListCell   *partexprs_item;
6091         int                     i;
6092
6093         if (rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
6094                 return false;
6095
6096         key = RelationGetPartitionKey(rel);
6097         partnatts = get_partition_natts(key);
6098         partexprs = get_partition_exprs(key);
6099
6100         partexprs_item = list_head(partexprs);
6101         for (i = 0; i < partnatts; i++)
6102         {
6103                 AttrNumber      partattno = get_partition_col_attnum(key, i);
6104
6105                 if (partattno != 0)
6106                 {
6107                         if (attnum == partattno)
6108                         {
6109                                 if (used_in_expr)
6110                                         *used_in_expr = false;
6111                                 return true;
6112                         }
6113                 }
6114                 else
6115                 {
6116                         /* Arbitrary expression */
6117                         Node       *expr = (Node *) lfirst(partexprs_item);
6118                         Bitmapset  *expr_attrs = NULL;
6119
6120                         /* Find all attributes referenced */
6121                         pull_varattnos(expr, 1, &expr_attrs);
6122                         partexprs_item = lnext(partexprs_item);
6123
6124                         if (bms_is_member(attnum - FirstLowInvalidHeapAttributeNumber,
6125                                                           expr_attrs))
6126                         {
6127                                 if (used_in_expr)
6128                                         *used_in_expr = true;
6129                                 return true;
6130                         }
6131                 }
6132         }
6133
6134         return false;
6135 }
6136
6137 /*
6138  * Return value is the address of the dropped column.
6139  */
6140 static ObjectAddress
6141 ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
6142                                  DropBehavior behavior,
6143                                  bool recurse, bool recursing,
6144                                  bool missing_ok, LOCKMODE lockmode)
6145 {
6146         HeapTuple       tuple;
6147         Form_pg_attribute targetatt;
6148         AttrNumber      attnum;
6149         List       *children;
6150         ObjectAddress object;
6151         bool            is_expr;
6152
6153         /* At top level, permission check was done in ATPrepCmd, else do it */
6154         if (recursing)
6155                 ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
6156
6157         /*
6158          * get the number of the attribute
6159          */
6160         tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
6161         if (!HeapTupleIsValid(tuple))
6162         {
6163                 if (!missing_ok)
6164                 {
6165                         ereport(ERROR,
6166                                         (errcode(ERRCODE_UNDEFINED_COLUMN),
6167                                          errmsg("column \"%s\" of relation \"%s\" does not exist",
6168                                                         colName, RelationGetRelationName(rel))));
6169                 }
6170                 else
6171                 {
6172                         ereport(NOTICE,
6173                                         (errmsg("column \"%s\" of relation \"%s\" does not exist, skipping",
6174                                                         colName, RelationGetRelationName(rel))));
6175                         return InvalidObjectAddress;
6176                 }
6177         }
6178         targetatt = (Form_pg_attribute) GETSTRUCT(tuple);
6179
6180         attnum = targetatt->attnum;
6181
6182         /* Can't drop a system attribute, except OID */
6183         if (attnum <= 0 && attnum != ObjectIdAttributeNumber)
6184                 ereport(ERROR,
6185                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
6186                                  errmsg("cannot drop system column \"%s\"",
6187                                                 colName)));
6188
6189         /* Don't drop inherited columns */
6190         if (targetatt->attinhcount > 0 && !recursing)
6191                 ereport(ERROR,
6192                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6193                                  errmsg("cannot drop inherited column \"%s\"",
6194                                                 colName)));
6195
6196         /* Don't drop columns used in the partition key */
6197         if (is_partition_attr(rel, attnum, &is_expr))
6198         {
6199                 if (!is_expr)
6200                         ereport(ERROR,
6201                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6202                                          errmsg("cannot drop column named in partition key")));
6203                 else
6204                         ereport(ERROR,
6205                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6206                                          errmsg("cannot drop column referenced in partition key expression")));
6207         }
6208
6209         ReleaseSysCache(tuple);
6210
6211         /*
6212          * Propagate to children as appropriate.  Unlike most other ALTER
6213          * routines, we have to do this one level of recursion at a time; we can't
6214          * use find_all_inheritors to do it in one pass.
6215          */
6216         children = find_inheritance_children(RelationGetRelid(rel), lockmode);
6217
6218         if (children)
6219         {
6220                 Relation        attr_rel;
6221                 ListCell   *child;
6222
6223                 /*
6224                  * In case of a partitioned table, the column must be dropped from the
6225                  * partitions as well.
6226                  */
6227                 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE && !recurse)
6228                         ereport(ERROR,
6229                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6230                                          errmsg("column must be dropped from child tables too")));
6231
6232                 attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
6233                 foreach(child, children)
6234                 {
6235                         Oid                     childrelid = lfirst_oid(child);
6236                         Relation        childrel;
6237                         Form_pg_attribute childatt;
6238
6239                         /* find_inheritance_children already got lock */
6240                         childrel = heap_open(childrelid, NoLock);
6241                         CheckTableNotInUse(childrel, "ALTER TABLE");
6242
6243                         tuple = SearchSysCacheCopyAttName(childrelid, colName);
6244                         if (!HeapTupleIsValid(tuple))           /* shouldn't happen */
6245                                 elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u",
6246                                          colName, childrelid);
6247                         childatt = (Form_pg_attribute) GETSTRUCT(tuple);
6248
6249                         if (childatt->attinhcount <= 0)         /* shouldn't happen */
6250                                 elog(ERROR, "relation %u has non-inherited attribute \"%s\"",
6251                                          childrelid, colName);
6252
6253                         if (recurse)
6254                         {
6255                                 /*
6256                                  * If the child column has other definition sources, just
6257                                  * decrement its inheritance count; if not, recurse to delete
6258                                  * it.
6259                                  */
6260                                 if (childatt->attinhcount == 1 && !childatt->attislocal)
6261                                 {
6262                                         /* Time to delete this child column, too */
6263                                         ATExecDropColumn(wqueue, childrel, colName,
6264                                                                          behavior, true, true,
6265                                                                          false, lockmode);
6266                                 }
6267                                 else
6268                                 {
6269                                         /* Child column must survive my deletion */
6270                                         childatt->attinhcount--;
6271
6272                                         CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
6273
6274                                         /* Make update visible */
6275                                         CommandCounterIncrement();
6276                                 }
6277                         }
6278                         else
6279                         {
6280                                 /*
6281                                  * If we were told to drop ONLY in this table (no recursion),
6282                                  * we need to mark the inheritors' attributes as locally
6283                                  * defined rather than inherited.
6284                                  */
6285                                 childatt->attinhcount--;
6286                                 childatt->attislocal = true;
6287
6288                                 CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
6289
6290                                 /* Make update visible */
6291                                 CommandCounterIncrement();
6292                         }
6293
6294                         heap_freetuple(tuple);
6295
6296                         heap_close(childrel, NoLock);
6297                 }
6298                 heap_close(attr_rel, RowExclusiveLock);
6299         }
6300
6301         /*
6302          * Perform the actual column deletion
6303          */
6304         object.classId = RelationRelationId;
6305         object.objectId = RelationGetRelid(rel);
6306         object.objectSubId = attnum;
6307
6308         performDeletion(&object, behavior, 0);
6309
6310         /*
6311          * If we dropped the OID column, must adjust pg_class.relhasoids and tell
6312          * Phase 3 to physically get rid of the column.  We formerly left the
6313          * column in place physically, but this caused subtle problems.  See
6314          * http://archives.postgresql.org/pgsql-hackers/2009-02/msg00363.php
6315          */
6316         if (attnum == ObjectIdAttributeNumber)
6317         {
6318                 Relation        class_rel;
6319                 Form_pg_class tuple_class;
6320                 AlteredTableInfo *tab;
6321
6322                 class_rel = heap_open(RelationRelationId, RowExclusiveLock);
6323
6324                 tuple = SearchSysCacheCopy1(RELOID,
6325                                                                         ObjectIdGetDatum(RelationGetRelid(rel)));
6326                 if (!HeapTupleIsValid(tuple))
6327                         elog(ERROR, "cache lookup failed for relation %u",
6328                                  RelationGetRelid(rel));
6329                 tuple_class = (Form_pg_class) GETSTRUCT(tuple);
6330
6331                 tuple_class->relhasoids = false;
6332                 CatalogTupleUpdate(class_rel, &tuple->t_self, tuple);
6333
6334                 heap_close(class_rel, RowExclusiveLock);
6335
6336                 /* Find or create work queue entry for this table */
6337                 tab = ATGetQueueEntry(wqueue, rel);
6338
6339                 /* Tell Phase 3 to physically remove the OID column */
6340                 tab->rewrite |= AT_REWRITE_ALTER_OID;
6341         }
6342
6343         return object;
6344 }
6345
6346 /*
6347  * ALTER TABLE ADD INDEX
6348  *
6349  * There is no such command in the grammar, but parse_utilcmd.c converts
6350  * UNIQUE and PRIMARY KEY constraints into AT_AddIndex subcommands.  This lets
6351  * us schedule creation of the index at the appropriate time during ALTER.
6352  *
6353  * Return value is the address of the new index.
6354  */
6355 static ObjectAddress
6356 ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
6357                            IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode)
6358 {
6359         bool            check_rights;
6360         bool            skip_build;
6361         bool            quiet;
6362         ObjectAddress address;
6363
6364         Assert(IsA(stmt, IndexStmt));
6365         Assert(!stmt->concurrent);
6366
6367         /* The IndexStmt has already been through transformIndexStmt */
6368         Assert(stmt->transformed);
6369
6370         /* suppress schema rights check when rebuilding existing index */
6371         check_rights = !is_rebuild;
6372         /* skip index build if phase 3 will do it or we're reusing an old one */
6373         skip_build = tab->rewrite > 0 || OidIsValid(stmt->oldNode);
6374         /* suppress notices when rebuilding existing index */
6375         quiet = is_rebuild;
6376
6377         address = DefineIndex(RelationGetRelid(rel),
6378                                                   stmt,
6379                                                   InvalidOid,   /* no predefined OID */
6380                                                   true, /* is_alter_table */
6381                                                   check_rights,
6382                                                   skip_build,
6383                                                   quiet);
6384
6385         /*
6386          * If TryReuseIndex() stashed a relfilenode for us, we used it for the new
6387          * index instead of building from scratch.  The DROP of the old edition of
6388          * this index will have scheduled the storage for deletion at commit, so
6389          * cancel that pending deletion.
6390          */
6391         if (OidIsValid(stmt->oldNode))
6392         {
6393                 Relation        irel = index_open(address.objectId, NoLock);
6394
6395                 RelationPreserveStorage(irel->rd_node, true);
6396                 index_close(irel, NoLock);
6397         }
6398
6399         return address;
6400 }
6401
6402 /*
6403  * ALTER TABLE ADD CONSTRAINT USING INDEX
6404  *
6405  * Returns the address of the new constraint.
6406  */
6407 static ObjectAddress
6408 ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
6409                                                  IndexStmt *stmt, LOCKMODE lockmode)
6410 {
6411         Oid                     index_oid = stmt->indexOid;
6412         Relation        indexRel;
6413         char       *indexName;
6414         IndexInfo  *indexInfo;
6415         char       *constraintName;
6416         char            constraintType;
6417         ObjectAddress address;
6418
6419         Assert(IsA(stmt, IndexStmt));
6420         Assert(OidIsValid(index_oid));
6421         Assert(stmt->isconstraint);
6422
6423         indexRel = index_open(index_oid, AccessShareLock);
6424
6425         indexName = pstrdup(RelationGetRelationName(indexRel));
6426
6427         indexInfo = BuildIndexInfo(indexRel);
6428
6429         /* this should have been checked at parse time */
6430         if (!indexInfo->ii_Unique)
6431                 elog(ERROR, "index \"%s\" is not unique", indexName);
6432
6433         /*
6434          * Determine name to assign to constraint.  We require a constraint to
6435          * have the same name as the underlying index; therefore, use the index's
6436          * existing name as the default constraint name, and if the user
6437          * explicitly gives some other name for the constraint, rename the index
6438          * to match.
6439          */
6440         constraintName = stmt->idxname;
6441         if (constraintName == NULL)
6442                 constraintName = indexName;
6443         else if (strcmp(constraintName, indexName) != 0)
6444         {
6445                 ereport(NOTICE,
6446                                 (errmsg("ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"",
6447                                                 indexName, constraintName)));
6448                 RenameRelationInternal(index_oid, constraintName, false);
6449         }
6450
6451         /* Extra checks needed if making primary key */
6452         if (stmt->primary)
6453                 index_check_primary_key(rel, indexInfo, true);
6454
6455         /* Note we currently don't support EXCLUSION constraints here */
6456         if (stmt->primary)
6457                 constraintType = CONSTRAINT_PRIMARY;
6458         else
6459                 constraintType = CONSTRAINT_UNIQUE;
6460
6461         /* Create the catalog entries for the constraint */
6462         address = index_constraint_create(rel,
6463                                                                           index_oid,
6464                                                                           indexInfo,
6465                                                                           constraintName,
6466                                                                           constraintType,
6467                                                                           stmt->deferrable,
6468                                                                           stmt->initdeferred,
6469                                                                           stmt->primary,
6470                                                                           true,         /* update pg_index */
6471                                                                           true,         /* remove old dependencies */
6472                                                                           allowSystemTableMods,
6473                                                                           false);       /* is_internal */
6474
6475         index_close(indexRel, NoLock);
6476
6477         return address;
6478 }
6479
6480 /*
6481  * ALTER TABLE ADD CONSTRAINT
6482  *
6483  * Return value is the address of the new constraint; if no constraint was
6484  * added, InvalidObjectAddress is returned.
6485  */
6486 static ObjectAddress
6487 ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
6488                                         Constraint *newConstraint, bool recurse, bool is_readd,
6489                                         LOCKMODE lockmode)
6490 {
6491         ObjectAddress address = InvalidObjectAddress;
6492
6493         Assert(IsA(newConstraint, Constraint));
6494
6495         /*
6496          * Currently, we only expect to see CONSTR_CHECK and CONSTR_FOREIGN nodes
6497          * arriving here (see the preprocessing done in parse_utilcmd.c).  Use a
6498          * switch anyway to make it easier to add more code later.
6499          */
6500         switch (newConstraint->contype)
6501         {
6502                 case CONSTR_CHECK:
6503                         address =
6504                                 ATAddCheckConstraint(wqueue, tab, rel,
6505                                                                          newConstraint, recurse, false, is_readd,
6506                                                                          lockmode);
6507                         break;
6508
6509                 case CONSTR_FOREIGN:
6510
6511                         /*
6512                          * Note that we currently never recurse for FK constraints, so the
6513                          * "recurse" flag is silently ignored.
6514                          *
6515                          * Assign or validate constraint name
6516                          */
6517                         if (newConstraint->conname)
6518                         {
6519                                 if (ConstraintNameIsUsed(CONSTRAINT_RELATION,
6520                                                                                  RelationGetRelid(rel),
6521                                                                                  RelationGetNamespace(rel),
6522                                                                                  newConstraint->conname))
6523                                         ereport(ERROR,
6524                                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
6525                                                          errmsg("constraint \"%s\" for relation \"%s\" already exists",
6526                                                                         newConstraint->conname,
6527                                                                         RelationGetRelationName(rel))));
6528                         }
6529                         else
6530                                 newConstraint->conname =
6531                                         ChooseConstraintName(RelationGetRelationName(rel),
6532                                                                    strVal(linitial(newConstraint->fk_attrs)),
6533                                                                                  "fkey",
6534                                                                                  RelationGetNamespace(rel),
6535                                                                                  NIL);
6536
6537                         address = ATAddForeignKeyConstraint(tab, rel, newConstraint,
6538                                                                                                 lockmode);
6539                         break;
6540
6541                 default:
6542                         elog(ERROR, "unrecognized constraint type: %d",
6543                                  (int) newConstraint->contype);
6544         }
6545
6546         return address;
6547 }
6548
6549 /*
6550  * Add a check constraint to a single table and its children.  Returns the
6551  * address of the constraint added to the parent relation, if one gets added,
6552  * or InvalidObjectAddress otherwise.
6553  *
6554  * Subroutine for ATExecAddConstraint.
6555  *
6556  * We must recurse to child tables during execution, rather than using
6557  * ALTER TABLE's normal prep-time recursion.  The reason is that all the
6558  * constraints *must* be given the same name, else they won't be seen as
6559  * related later.  If the user didn't explicitly specify a name, then
6560  * AddRelationNewConstraints would normally assign different names to the
6561  * child constraints.  To fix that, we must capture the name assigned at
6562  * the parent table and pass that down.
6563  */
6564 static ObjectAddress
6565 ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
6566                                          Constraint *constr, bool recurse, bool recursing,
6567                                          bool is_readd, LOCKMODE lockmode)
6568 {
6569         List       *newcons;
6570         ListCell   *lcon;
6571         List       *children;
6572         ListCell   *child;
6573         ObjectAddress address = InvalidObjectAddress;
6574
6575         /* At top level, permission check was done in ATPrepCmd, else do it */
6576         if (recursing)
6577                 ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
6578
6579         /*
6580          * Call AddRelationNewConstraints to do the work, making sure it works on
6581          * a copy of the Constraint so transformExpr can't modify the original. It
6582          * returns a list of cooked constraints.
6583          *
6584          * If the constraint ends up getting merged with a pre-existing one, it's
6585          * omitted from the returned list, which is what we want: we do not need
6586          * to do any validation work.  That can only happen at child tables,
6587          * though, since we disallow merging at the top level.
6588          */
6589         newcons = AddRelationNewConstraints(rel, NIL,
6590                                                                                 list_make1(copyObject(constr)),
6591                                                                                 recursing | is_readd,   /* allow_merge */
6592                                                                                 !recursing,             /* is_local */
6593                                                                                 is_readd);              /* is_internal */
6594
6595         /* we don't expect more than one constraint here */
6596         Assert(list_length(newcons) <= 1);
6597
6598         /* Add each to-be-validated constraint to Phase 3's queue */
6599         foreach(lcon, newcons)
6600         {
6601                 CookedConstraint *ccon = (CookedConstraint *) lfirst(lcon);
6602
6603                 if (!ccon->skip_validation)
6604                 {
6605                         NewConstraint *newcon;
6606
6607                         newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
6608                         newcon->name = ccon->name;
6609                         newcon->contype = ccon->contype;
6610                         /* ExecQual wants implicit-AND format */
6611                         newcon->qual = (Node *) make_ands_implicit((Expr *) ccon->expr);
6612
6613                         tab->constraints = lappend(tab->constraints, newcon);
6614                 }
6615
6616                 /* Save the actually assigned name if it was defaulted */
6617                 if (constr->conname == NULL)
6618                         constr->conname = ccon->name;
6619
6620                 ObjectAddressSet(address, ConstraintRelationId, ccon->conoid);
6621         }
6622
6623         /* At this point we must have a locked-down name to use */
6624         Assert(constr->conname != NULL);
6625
6626         /* Advance command counter in case same table is visited multiple times */
6627         CommandCounterIncrement();
6628
6629         /*
6630          * If the constraint got merged with an existing constraint, we're done.
6631          * We mustn't recurse to child tables in this case, because they've
6632          * already got the constraint, and visiting them again would lead to an
6633          * incorrect value for coninhcount.
6634          */
6635         if (newcons == NIL)
6636                 return address;
6637
6638         /*
6639          * If adding a NO INHERIT constraint, no need to find our children.
6640          */
6641         if (constr->is_no_inherit)
6642                 return address;
6643
6644         /*
6645          * Propagate to children as appropriate.  Unlike most other ALTER
6646          * routines, we have to do this one level of recursion at a time; we can't
6647          * use find_all_inheritors to do it in one pass.
6648          */
6649         children = find_inheritance_children(RelationGetRelid(rel), lockmode);
6650
6651         /*
6652          * Check if ONLY was specified with ALTER TABLE.  If so, allow the
6653          * constraint creation only if there are no children currently.  Error out
6654          * otherwise.
6655          */
6656         if (!recurse && children != NIL)
6657                 ereport(ERROR,
6658                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6659                                  errmsg("constraint must be added to child tables too")));
6660
6661         foreach(child, children)
6662         {
6663                 Oid                     childrelid = lfirst_oid(child);
6664                 Relation        childrel;
6665                 AlteredTableInfo *childtab;
6666
6667                 /* find_inheritance_children already got lock */
6668                 childrel = heap_open(childrelid, NoLock);
6669                 CheckTableNotInUse(childrel, "ALTER TABLE");
6670
6671                 /* Find or create work queue entry for this table */
6672                 childtab = ATGetQueueEntry(wqueue, childrel);
6673
6674                 /* Recurse to child */
6675                 ATAddCheckConstraint(wqueue, childtab, childrel,
6676                                                          constr, recurse, true, is_readd, lockmode);
6677
6678                 heap_close(childrel, NoLock);
6679         }
6680
6681         return address;
6682 }
6683
6684 /*
6685  * Add a foreign-key constraint to a single table; return the new constraint's
6686  * address.
6687  *
6688  * Subroutine for ATExecAddConstraint.  Must already hold exclusive
6689  * lock on the rel, and have done appropriate validity checks for it.
6690  * We do permissions checks here, however.
6691  */
6692 static ObjectAddress
6693 ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
6694                                                   Constraint *fkconstraint, LOCKMODE lockmode)
6695 {
6696         Relation        pkrel;
6697         int16           pkattnum[INDEX_MAX_KEYS];
6698         int16           fkattnum[INDEX_MAX_KEYS];
6699         Oid                     pktypoid[INDEX_MAX_KEYS];
6700         Oid                     fktypoid[INDEX_MAX_KEYS];
6701         Oid                     opclasses[INDEX_MAX_KEYS];
6702         Oid                     pfeqoperators[INDEX_MAX_KEYS];
6703         Oid                     ppeqoperators[INDEX_MAX_KEYS];
6704         Oid                     ffeqoperators[INDEX_MAX_KEYS];
6705         int                     i;
6706         int                     numfks,
6707                                 numpks;
6708         Oid                     indexOid;
6709         Oid                     constrOid;
6710         bool            old_check_ok;
6711         ObjectAddress address;
6712         ListCell   *old_pfeqop_item = list_head(fkconstraint->old_conpfeqop);
6713
6714         /*
6715          * Grab ShareRowExclusiveLock on the pk table, so that someone doesn't
6716          * delete rows out from under us.
6717          */
6718         if (OidIsValid(fkconstraint->old_pktable_oid))
6719                 pkrel = heap_open(fkconstraint->old_pktable_oid, ShareRowExclusiveLock);
6720         else
6721                 pkrel = heap_openrv(fkconstraint->pktable, ShareRowExclusiveLock);
6722
6723         /*
6724          * Validity checks (permission checks wait till we have the column
6725          * numbers)
6726          */
6727         if (pkrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6728                 ereport(ERROR,
6729                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
6730                                  errmsg("cannot reference partitioned table \"%s\"",
6731                                                 RelationGetRelationName(pkrel))));
6732
6733         if (pkrel->rd_rel->relkind != RELKIND_RELATION)
6734                 ereport(ERROR,
6735                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
6736                                  errmsg("referenced relation \"%s\" is not a table",
6737                                                 RelationGetRelationName(pkrel))));
6738
6739         if (!allowSystemTableMods && IsSystemRelation(pkrel))
6740                 ereport(ERROR,
6741                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
6742                                  errmsg("permission denied: \"%s\" is a system catalog",
6743                                                 RelationGetRelationName(pkrel))));
6744
6745         /*
6746          * References from permanent or unlogged tables to temp tables, and from
6747          * permanent tables to unlogged tables, are disallowed because the
6748          * referenced data can vanish out from under us.  References from temp
6749          * tables to any other table type are also disallowed, because other
6750          * backends might need to run the RI triggers on the perm table, but they
6751          * can't reliably see tuples in the local buffers of other backends.
6752          */
6753         switch (rel->rd_rel->relpersistence)
6754         {
6755                 case RELPERSISTENCE_PERMANENT:
6756                         if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT)
6757                                 ereport(ERROR,
6758                                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6759                                                  errmsg("constraints on permanent tables may reference only permanent tables")));
6760                         break;
6761                 case RELPERSISTENCE_UNLOGGED:
6762                         if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT
6763                                 && pkrel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED)
6764                                 ereport(ERROR,
6765                                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6766                                                  errmsg("constraints on unlogged tables may reference only permanent or unlogged tables")));
6767                         break;
6768                 case RELPERSISTENCE_TEMP:
6769                         if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_TEMP)
6770                                 ereport(ERROR,
6771                                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6772                                                  errmsg("constraints on temporary tables may reference only temporary tables")));
6773                         if (!pkrel->rd_islocaltemp || !rel->rd_islocaltemp)
6774                                 ereport(ERROR,
6775                                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6776                                                  errmsg("constraints on temporary tables must involve temporary tables of this session")));
6777                         break;
6778         }
6779
6780         /*
6781          * Look up the referencing attributes to make sure they exist, and record
6782          * their attnums and type OIDs.
6783          */
6784         MemSet(pkattnum, 0, sizeof(pkattnum));
6785         MemSet(fkattnum, 0, sizeof(fkattnum));
6786         MemSet(pktypoid, 0, sizeof(pktypoid));
6787         MemSet(fktypoid, 0, sizeof(fktypoid));
6788         MemSet(opclasses, 0, sizeof(opclasses));
6789         MemSet(pfeqoperators, 0, sizeof(pfeqoperators));
6790         MemSet(ppeqoperators, 0, sizeof(ppeqoperators));
6791         MemSet(ffeqoperators, 0, sizeof(ffeqoperators));
6792
6793         numfks = transformColumnNameList(RelationGetRelid(rel),
6794                                                                          fkconstraint->fk_attrs,
6795                                                                          fkattnum, fktypoid);
6796
6797         /*
6798          * If the attribute list for the referenced table was omitted, lookup the
6799          * definition of the primary key and use it.  Otherwise, validate the
6800          * supplied attribute list.  In either case, discover the index OID and
6801          * index opclasses, and the attnums and type OIDs of the attributes.
6802          */
6803         if (fkconstraint->pk_attrs == NIL)
6804         {
6805                 numpks = transformFkeyGetPrimaryKey(pkrel, &indexOid,
6806                                                                                         &fkconstraint->pk_attrs,
6807                                                                                         pkattnum, pktypoid,
6808                                                                                         opclasses);
6809         }
6810         else
6811         {
6812                 numpks = transformColumnNameList(RelationGetRelid(pkrel),
6813                                                                                  fkconstraint->pk_attrs,
6814                                                                                  pkattnum, pktypoid);
6815                 /* Look for an index matching the column list */
6816                 indexOid = transformFkeyCheckAttrs(pkrel, numpks, pkattnum,
6817                                                                                    opclasses);
6818         }
6819
6820         /*
6821          * Now we can check permissions.
6822          */
6823         checkFkeyPermissions(pkrel, pkattnum, numpks);
6824         checkFkeyPermissions(rel, fkattnum, numfks);
6825
6826         /*
6827          * Look up the equality operators to use in the constraint.
6828          *
6829          * Note that we have to be careful about the difference between the actual
6830          * PK column type and the opclass' declared input type, which might be
6831          * only binary-compatible with it.  The declared opcintype is the right
6832          * thing to probe pg_amop with.
6833          */
6834         if (numfks != numpks)
6835                 ereport(ERROR,
6836                                 (errcode(ERRCODE_INVALID_FOREIGN_KEY),
6837                                  errmsg("number of referencing and referenced columns for foreign key disagree")));
6838
6839         /*
6840          * On the strength of a previous constraint, we might avoid scanning
6841          * tables to validate this one.  See below.
6842          */
6843         old_check_ok = (fkconstraint->old_conpfeqop != NIL);
6844         Assert(!old_check_ok || numfks == list_length(fkconstraint->old_conpfeqop));
6845
6846         for (i = 0; i < numpks; i++)
6847         {
6848                 Oid                     pktype = pktypoid[i];
6849                 Oid                     fktype = fktypoid[i];
6850                 Oid                     fktyped;
6851                 HeapTuple       cla_ht;
6852                 Form_pg_opclass cla_tup;
6853                 Oid                     amid;
6854                 Oid                     opfamily;
6855                 Oid                     opcintype;
6856                 Oid                     pfeqop;
6857                 Oid                     ppeqop;
6858                 Oid                     ffeqop;
6859                 int16           eqstrategy;
6860                 Oid                     pfeqop_right;
6861
6862                 /* We need several fields out of the pg_opclass entry */
6863                 cla_ht = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclasses[i]));
6864                 if (!HeapTupleIsValid(cla_ht))
6865                         elog(ERROR, "cache lookup failed for opclass %u", opclasses[i]);
6866                 cla_tup = (Form_pg_opclass) GETSTRUCT(cla_ht);
6867                 amid = cla_tup->opcmethod;
6868                 opfamily = cla_tup->opcfamily;
6869                 opcintype = cla_tup->opcintype;
6870                 ReleaseSysCache(cla_ht);
6871
6872                 /*
6873                  * Check it's a btree; currently this can never fail since no other
6874                  * index AMs support unique indexes.  If we ever did have other types
6875                  * of unique indexes, we'd need a way to determine which operator
6876                  * strategy number is equality.  (Is it reasonable to insist that
6877                  * every such index AM use btree's number for equality?)
6878                  */
6879                 if (amid != BTREE_AM_OID)
6880                         elog(ERROR, "only b-tree indexes are supported for foreign keys");
6881                 eqstrategy = BTEqualStrategyNumber;
6882
6883                 /*
6884                  * There had better be a primary equality operator for the index.
6885                  * We'll use it for PK = PK comparisons.
6886                  */
6887                 ppeqop = get_opfamily_member(opfamily, opcintype, opcintype,
6888                                                                          eqstrategy);
6889
6890                 if (!OidIsValid(ppeqop))
6891                         elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
6892                                  eqstrategy, opcintype, opcintype, opfamily);
6893
6894                 /*
6895                  * Are there equality operators that take exactly the FK type? Assume
6896                  * we should look through any domain here.
6897                  */
6898                 fktyped = getBaseType(fktype);
6899
6900                 pfeqop = get_opfamily_member(opfamily, opcintype, fktyped,
6901                                                                          eqstrategy);
6902                 if (OidIsValid(pfeqop))
6903                 {
6904                         pfeqop_right = fktyped;
6905                         ffeqop = get_opfamily_member(opfamily, fktyped, fktyped,
6906                                                                                  eqstrategy);
6907                 }
6908                 else
6909                 {
6910                         /* keep compiler quiet */
6911                         pfeqop_right = InvalidOid;
6912                         ffeqop = InvalidOid;
6913                 }
6914
6915                 if (!(OidIsValid(pfeqop) && OidIsValid(ffeqop)))
6916                 {
6917                         /*
6918                          * Otherwise, look for an implicit cast from the FK type to the
6919                          * opcintype, and if found, use the primary equality operator.
6920                          * This is a bit tricky because opcintype might be a polymorphic
6921                          * type such as ANYARRAY or ANYENUM; so what we have to test is
6922                          * whether the two actual column types can be concurrently cast to
6923                          * that type.  (Otherwise, we'd fail to reject combinations such
6924                          * as int[] and point[].)
6925                          */
6926                         Oid                     input_typeids[2];
6927                         Oid                     target_typeids[2];
6928
6929                         input_typeids[0] = pktype;
6930                         input_typeids[1] = fktype;
6931                         target_typeids[0] = opcintype;
6932                         target_typeids[1] = opcintype;
6933                         if (can_coerce_type(2, input_typeids, target_typeids,
6934                                                                 COERCION_IMPLICIT))
6935                         {
6936                                 pfeqop = ffeqop = ppeqop;
6937                                 pfeqop_right = opcintype;
6938                         }
6939                 }
6940
6941                 if (!(OidIsValid(pfeqop) && OidIsValid(ffeqop)))
6942                         ereport(ERROR,
6943                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
6944                                          errmsg("foreign key constraint \"%s\" "
6945                                                         "cannot be implemented",
6946                                                         fkconstraint->conname),
6947                                          errdetail("Key columns \"%s\" and \"%s\" "
6948                                                            "are of incompatible types: %s and %s.",
6949                                                            strVal(list_nth(fkconstraint->fk_attrs, i)),
6950                                                            strVal(list_nth(fkconstraint->pk_attrs, i)),
6951                                                            format_type_be(fktype),
6952                                                            format_type_be(pktype))));
6953
6954                 if (old_check_ok)
6955                 {
6956                         /*
6957                          * When a pfeqop changes, revalidate the constraint.  We could
6958                          * permit intra-opfamily changes, but that adds subtle complexity
6959                          * without any concrete benefit for core types.  We need not
6960                          * assess ppeqop or ffeqop, which RI_Initial_Check() does not use.
6961                          */
6962                         old_check_ok = (pfeqop == lfirst_oid(old_pfeqop_item));
6963                         old_pfeqop_item = lnext(old_pfeqop_item);
6964                 }
6965                 if (old_check_ok)
6966                 {
6967                         Oid                     old_fktype;
6968                         Oid                     new_fktype;
6969                         CoercionPathType old_pathtype;
6970                         CoercionPathType new_pathtype;
6971                         Oid                     old_castfunc;
6972                         Oid                     new_castfunc;
6973
6974                         /*
6975                          * Identify coercion pathways from each of the old and new FK-side
6976                          * column types to the right (foreign) operand type of the pfeqop.
6977                          * We may assume that pg_constraint.conkey is not changing.
6978                          */
6979                         old_fktype = tab->oldDesc->attrs[fkattnum[i] - 1]->atttypid;
6980                         new_fktype = fktype;
6981                         old_pathtype = findFkeyCast(pfeqop_right, old_fktype,
6982                                                                                 &old_castfunc);
6983                         new_pathtype = findFkeyCast(pfeqop_right, new_fktype,
6984                                                                                 &new_castfunc);
6985
6986                         /*
6987                          * Upon a change to the cast from the FK column to its pfeqop
6988                          * operand, revalidate the constraint.  For this evaluation, a
6989                          * binary coercion cast is equivalent to no cast at all.  While
6990                          * type implementors should design implicit casts with an eye
6991                          * toward consistency of operations like equality, we cannot
6992                          * assume here that they have done so.
6993                          *
6994                          * A function with a polymorphic argument could change behavior
6995                          * arbitrarily in response to get_fn_expr_argtype().  Therefore,
6996                          * when the cast destination is polymorphic, we only avoid
6997                          * revalidation if the input type has not changed at all.  Given
6998                          * just the core data types and operator classes, this requirement
6999                          * prevents no would-be optimizations.
7000                          *
7001                          * If the cast converts from a base type to a domain thereon, then
7002                          * that domain type must be the opcintype of the unique index.
7003                          * Necessarily, the primary key column must then be of the domain
7004                          * type.  Since the constraint was previously valid, all values on
7005                          * the foreign side necessarily exist on the primary side and in
7006                          * turn conform to the domain.  Consequently, we need not treat
7007                          * domains specially here.
7008                          *
7009                          * Since we require that all collations share the same notion of
7010                          * equality (which they do, because texteq reduces to bitwise
7011                          * equality), we don't compare collation here.
7012                          *
7013                          * We need not directly consider the PK type.  It's necessarily
7014                          * binary coercible to the opcintype of the unique index column,
7015                          * and ri_triggers.c will only deal with PK datums in terms of
7016                          * that opcintype.  Changing the opcintype also changes pfeqop.
7017                          */
7018                         old_check_ok = (new_pathtype == old_pathtype &&
7019                                                         new_castfunc == old_castfunc &&
7020                                                         (!IsPolymorphicType(pfeqop_right) ||
7021                                                          new_fktype == old_fktype));
7022
7023                 }
7024
7025                 pfeqoperators[i] = pfeqop;
7026                 ppeqoperators[i] = ppeqop;
7027                 ffeqoperators[i] = ffeqop;
7028         }
7029
7030         /*
7031          * Record the FK constraint in pg_constraint.
7032          */
7033         constrOid = CreateConstraintEntry(fkconstraint->conname,
7034                                                                           RelationGetNamespace(rel),
7035                                                                           CONSTRAINT_FOREIGN,
7036                                                                           fkconstraint->deferrable,
7037                                                                           fkconstraint->initdeferred,
7038                                                                           fkconstraint->initially_valid,
7039                                                                           RelationGetRelid(rel),
7040                                                                           fkattnum,
7041                                                                           numfks,
7042                                                                           InvalidOid,           /* not a domain
7043                                                                                                                  * constraint */
7044                                                                           indexOid,
7045                                                                           RelationGetRelid(pkrel),
7046                                                                           pkattnum,
7047                                                                           pfeqoperators,
7048                                                                           ppeqoperators,
7049                                                                           ffeqoperators,
7050                                                                           numpks,
7051                                                                           fkconstraint->fk_upd_action,
7052                                                                           fkconstraint->fk_del_action,
7053                                                                           fkconstraint->fk_matchtype,
7054                                                                           NULL,         /* no exclusion constraint */
7055                                                                           NULL,         /* no check constraint */
7056                                                                           NULL,
7057                                                                           NULL,
7058                                                                           true,         /* islocal */
7059                                                                           0,            /* inhcount */
7060                                                                           true,         /* isnoinherit */
7061                                                                           false);       /* is_internal */
7062         ObjectAddressSet(address, ConstraintRelationId, constrOid);
7063
7064         /*
7065          * Create the triggers that will enforce the constraint.
7066          */
7067         createForeignKeyTriggers(rel, RelationGetRelid(pkrel), fkconstraint,
7068                                                          constrOid, indexOid);
7069
7070         /*
7071          * Tell Phase 3 to check that the constraint is satisfied by existing
7072          * rows. We can skip this during table creation, when requested explicitly
7073          * by specifying NOT VALID in an ADD FOREIGN KEY command, and when we're
7074          * recreating a constraint following a SET DATA TYPE operation that did
7075          * not impugn its validity.
7076          */
7077         if (!old_check_ok && !fkconstraint->skip_validation)
7078         {
7079                 NewConstraint *newcon;
7080
7081                 newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
7082                 newcon->name = fkconstraint->conname;
7083                 newcon->contype = CONSTR_FOREIGN;
7084                 newcon->refrelid = RelationGetRelid(pkrel);
7085                 newcon->refindid = indexOid;
7086                 newcon->conid = constrOid;
7087                 newcon->qual = (Node *) fkconstraint;
7088
7089                 tab->constraints = lappend(tab->constraints, newcon);
7090         }
7091
7092         /*
7093          * Close pk table, but keep lock until we've committed.
7094          */
7095         heap_close(pkrel, NoLock);
7096
7097         return address;
7098 }
7099
7100 /*
7101  * ALTER TABLE ALTER CONSTRAINT
7102  *
7103  * Update the attributes of a constraint.
7104  *
7105  * Currently only works for Foreign Key constraints.
7106  * Foreign keys do not inherit, so we purposely ignore the
7107  * recursion bit here, but we keep the API the same for when
7108  * other constraint types are supported.
7109  *
7110  * If the constraint is modified, returns its address; otherwise, return
7111  * InvalidObjectAddress.
7112  */
7113 static ObjectAddress
7114 ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
7115                                           bool recurse, bool recursing, LOCKMODE lockmode)
7116 {
7117         Constraint *cmdcon;
7118         Relation        conrel;
7119         SysScanDesc scan;
7120         ScanKeyData key;
7121         HeapTuple       contuple;
7122         Form_pg_constraint currcon = NULL;
7123         bool            found = false;
7124         ObjectAddress address;
7125
7126         cmdcon = castNode(Constraint, cmd->def);
7127
7128         conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
7129
7130         /*
7131          * Find and check the target constraint
7132          */
7133         ScanKeyInit(&key,
7134                                 Anum_pg_constraint_conrelid,
7135                                 BTEqualStrategyNumber, F_OIDEQ,
7136                                 ObjectIdGetDatum(RelationGetRelid(rel)));
7137         scan = systable_beginscan(conrel, ConstraintRelidIndexId,
7138                                                           true, NULL, 1, &key);
7139
7140         while (HeapTupleIsValid(contuple = systable_getnext(scan)))
7141         {
7142                 currcon = (Form_pg_constraint) GETSTRUCT(contuple);
7143                 if (strcmp(NameStr(currcon->conname), cmdcon->conname) == 0)
7144                 {
7145                         found = true;
7146                         break;
7147                 }
7148         }
7149
7150         if (!found)
7151                 ereport(ERROR,
7152                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
7153                                  errmsg("constraint \"%s\" of relation \"%s\" does not exist",
7154                                                 cmdcon->conname, RelationGetRelationName(rel))));
7155
7156         if (currcon->contype != CONSTRAINT_FOREIGN)
7157                 ereport(ERROR,
7158                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
7159                                  errmsg("constraint \"%s\" of relation \"%s\" is not a foreign key constraint",
7160                                                 cmdcon->conname, RelationGetRelationName(rel))));
7161
7162         if (currcon->condeferrable != cmdcon->deferrable ||
7163                 currcon->condeferred != cmdcon->initdeferred)
7164         {
7165                 HeapTuple       copyTuple;
7166                 HeapTuple       tgtuple;
7167                 Form_pg_constraint copy_con;
7168                 List       *otherrelids = NIL;
7169                 ScanKeyData tgkey;
7170                 SysScanDesc tgscan;
7171                 Relation        tgrel;
7172                 ListCell   *lc;
7173
7174                 /*
7175                  * Now update the catalog, while we have the door open.
7176                  */
7177                 copyTuple = heap_copytuple(contuple);
7178                 copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
7179                 copy_con->condeferrable = cmdcon->deferrable;
7180                 copy_con->condeferred = cmdcon->initdeferred;
7181                 CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
7182
7183                 InvokeObjectPostAlterHook(ConstraintRelationId,
7184                                                                   HeapTupleGetOid(contuple), 0);
7185
7186                 heap_freetuple(copyTuple);
7187
7188                 /*
7189                  * Now we need to update the multiple entries in pg_trigger that
7190                  * implement the constraint.
7191                  */
7192                 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
7193
7194                 ScanKeyInit(&tgkey,
7195                                         Anum_pg_trigger_tgconstraint,
7196                                         BTEqualStrategyNumber, F_OIDEQ,
7197                                         ObjectIdGetDatum(HeapTupleGetOid(contuple)));
7198
7199                 tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
7200                                                                         NULL, 1, &tgkey);
7201
7202                 while (HeapTupleIsValid(tgtuple = systable_getnext(tgscan)))
7203                 {
7204                         Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple);
7205                         Form_pg_trigger copy_tg;
7206
7207                         /*
7208                          * Remember OIDs of other relation(s) involved in FK constraint.
7209                          * (Note: it's likely that we could skip forcing a relcache inval
7210                          * for other rels that don't have a trigger whose properties
7211                          * change, but let's be conservative.)
7212                          */
7213                         if (tgform->tgrelid != RelationGetRelid(rel))
7214                                 otherrelids = list_append_unique_oid(otherrelids,
7215                                                                                                          tgform->tgrelid);
7216
7217                         /*
7218                          * Update deferrability of RI_FKey_noaction_del,
7219                          * RI_FKey_noaction_upd, RI_FKey_check_ins and RI_FKey_check_upd
7220                          * triggers, but not others; see createForeignKeyTriggers and
7221                          * CreateFKCheckTrigger.
7222                          */
7223                         if (tgform->tgfoid != F_RI_FKEY_NOACTION_DEL &&
7224                                 tgform->tgfoid != F_RI_FKEY_NOACTION_UPD &&
7225                                 tgform->tgfoid != F_RI_FKEY_CHECK_INS &&
7226                                 tgform->tgfoid != F_RI_FKEY_CHECK_UPD)
7227                                 continue;
7228
7229                         copyTuple = heap_copytuple(tgtuple);
7230                         copy_tg = (Form_pg_trigger) GETSTRUCT(copyTuple);
7231
7232                         copy_tg->tgdeferrable = cmdcon->deferrable;
7233                         copy_tg->tginitdeferred = cmdcon->initdeferred;
7234                         CatalogTupleUpdate(tgrel, &copyTuple->t_self, copyTuple);
7235
7236                         InvokeObjectPostAlterHook(TriggerRelationId,
7237                                                                           HeapTupleGetOid(tgtuple), 0);
7238
7239                         heap_freetuple(copyTuple);
7240                 }
7241
7242                 systable_endscan(tgscan);
7243
7244                 heap_close(tgrel, RowExclusiveLock);
7245
7246                 /*
7247                  * Invalidate relcache so that others see the new attributes.  We must
7248                  * inval both the named rel and any others having relevant triggers.
7249                  * (At present there should always be exactly one other rel, but
7250                  * there's no need to hard-wire such an assumption here.)
7251                  */
7252                 CacheInvalidateRelcache(rel);
7253                 foreach(lc, otherrelids)
7254                 {
7255                         CacheInvalidateRelcacheByRelid(lfirst_oid(lc));
7256                 }
7257
7258                 ObjectAddressSet(address, ConstraintRelationId,
7259                                                  HeapTupleGetOid(contuple));
7260         }
7261         else
7262                 address = InvalidObjectAddress;
7263
7264         systable_endscan(scan);
7265
7266         heap_close(conrel, RowExclusiveLock);
7267
7268         return address;
7269 }
7270
7271 /*
7272  * ALTER TABLE VALIDATE CONSTRAINT
7273  *
7274  * XXX The reason we handle recursion here rather than at Phase 1 is because
7275  * there's no good way to skip recursing when handling foreign keys: there is
7276  * no need to lock children in that case, yet we wouldn't be able to avoid
7277  * doing so at that level.
7278  *
7279  * Return value is the address of the validated constraint.  If the constraint
7280  * was already validated, InvalidObjectAddress is returned.
7281  */
7282 static ObjectAddress
7283 ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
7284                                                  bool recursing, LOCKMODE lockmode)
7285 {
7286         Relation        conrel;
7287         SysScanDesc scan;
7288         ScanKeyData key;
7289         HeapTuple       tuple;
7290         Form_pg_constraint con = NULL;
7291         bool            found = false;
7292         ObjectAddress address;
7293
7294         conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
7295
7296         /*
7297          * Find and check the target constraint
7298          */
7299         ScanKeyInit(&key,
7300                                 Anum_pg_constraint_conrelid,
7301                                 BTEqualStrategyNumber, F_OIDEQ,
7302                                 ObjectIdGetDatum(RelationGetRelid(rel)));
7303         scan = systable_beginscan(conrel, ConstraintRelidIndexId,
7304                                                           true, NULL, 1, &key);
7305
7306         while (HeapTupleIsValid(tuple = systable_getnext(scan)))
7307         {
7308                 con = (Form_pg_constraint) GETSTRUCT(tuple);
7309                 if (strcmp(NameStr(con->conname), constrName) == 0)
7310                 {
7311                         found = true;
7312                         break;
7313                 }
7314         }
7315
7316         if (!found)
7317                 ereport(ERROR,
7318                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
7319                                  errmsg("constraint \"%s\" of relation \"%s\" does not exist",
7320                                                 constrName, RelationGetRelationName(rel))));
7321
7322         if (con->contype != CONSTRAINT_FOREIGN &&
7323                 con->contype != CONSTRAINT_CHECK)
7324                 ereport(ERROR,
7325                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
7326                                  errmsg("constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint",
7327                                                 constrName, RelationGetRelationName(rel))));
7328
7329         if (!con->convalidated)
7330         {
7331                 HeapTuple       copyTuple;
7332                 Form_pg_constraint copy_con;
7333
7334                 if (con->contype == CONSTRAINT_FOREIGN)
7335                 {
7336                         Relation        refrel;
7337
7338                         /*
7339                          * Triggers are already in place on both tables, so a concurrent
7340                          * write that alters the result here is not possible. Normally we
7341                          * can run a query here to do the validation, which would only
7342                          * require AccessShareLock. In some cases, it is possible that we
7343                          * might need to fire triggers to perform the check, so we take a
7344                          * lock at RowShareLock level just in case.
7345                          */
7346                         refrel = heap_open(con->confrelid, RowShareLock);
7347
7348                         validateForeignKeyConstraint(constrName, rel, refrel,
7349                                                                                  con->conindid,
7350                                                                                  HeapTupleGetOid(tuple));
7351                         heap_close(refrel, NoLock);
7352
7353                         /*
7354                          * Foreign keys do not inherit, so we purposely ignore the
7355                          * recursion bit here
7356                          */
7357                 }
7358                 else if (con->contype == CONSTRAINT_CHECK)
7359                 {
7360                         List       *children = NIL;
7361                         ListCell   *child;
7362
7363                         /*
7364                          * If we're recursing, the parent has already done this, so skip
7365                          * it.
7366                          */
7367                         if (!recursing)
7368                                 children = find_all_inheritors(RelationGetRelid(rel),
7369                                                                                            lockmode, NULL);
7370
7371                         /*
7372                          * For CHECK constraints, we must ensure that we only mark the
7373                          * constraint as validated on the parent if it's already validated
7374                          * on the children.
7375                          *
7376                          * We recurse before validating on the parent, to reduce risk of
7377                          * deadlocks.
7378                          */
7379                         foreach(child, children)
7380                         {
7381                                 Oid                     childoid = lfirst_oid(child);
7382                                 Relation        childrel;
7383
7384                                 if (childoid == RelationGetRelid(rel))
7385                                         continue;
7386
7387                                 /*
7388                                  * If we are told not to recurse, there had better not be any
7389                                  * child tables, because we can't mark the constraint on the
7390                                  * parent valid unless it is valid for all child tables.
7391                                  */
7392                                 if (!recurse)
7393                                         ereport(ERROR,
7394                                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
7395                                                          errmsg("constraint must be validated on child tables too")));
7396
7397                                 /* find_all_inheritors already got lock */
7398                                 childrel = heap_open(childoid, NoLock);
7399
7400                                 ATExecValidateConstraint(childrel, constrName, false,
7401                                                                                  true, lockmode);
7402                                 heap_close(childrel, NoLock);
7403                         }
7404
7405                         validateCheckConstraint(rel, tuple);
7406
7407                         /*
7408                          * Invalidate relcache so that others see the new validated
7409                          * constraint.
7410                          */
7411                         CacheInvalidateRelcache(rel);
7412                 }
7413
7414                 /*
7415                  * Now update the catalog, while we have the door open.
7416                  */
7417                 copyTuple = heap_copytuple(tuple);
7418                 copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
7419                 copy_con->convalidated = true;
7420                 CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
7421
7422                 InvokeObjectPostAlterHook(ConstraintRelationId,
7423                                                                   HeapTupleGetOid(tuple), 0);
7424
7425                 heap_freetuple(copyTuple);
7426
7427                 ObjectAddressSet(address, ConstraintRelationId,
7428                                                  HeapTupleGetOid(tuple));
7429         }
7430         else
7431                 address = InvalidObjectAddress; /* already validated */
7432
7433         systable_endscan(scan);
7434
7435         heap_close(conrel, RowExclusiveLock);
7436
7437         return address;
7438 }
7439
7440
7441 /*
7442  * transformColumnNameList - transform list of column names
7443  *
7444  * Lookup each name and return its attnum and type OID
7445  */
7446 static int
7447 transformColumnNameList(Oid relId, List *colList,
7448                                                 int16 *attnums, Oid *atttypids)
7449 {
7450         ListCell   *l;
7451         int                     attnum;
7452
7453         attnum = 0;
7454         foreach(l, colList)
7455         {
7456                 char       *attname = strVal(lfirst(l));
7457                 HeapTuple       atttuple;
7458
7459                 atttuple = SearchSysCacheAttName(relId, attname);
7460                 if (!HeapTupleIsValid(atttuple))
7461                         ereport(ERROR,
7462                                         (errcode(ERRCODE_UNDEFINED_COLUMN),
7463                                          errmsg("column \"%s\" referenced in foreign key constraint does not exist",
7464                                                         attname)));
7465                 if (attnum >= INDEX_MAX_KEYS)
7466                         ereport(ERROR,
7467                                         (errcode(ERRCODE_TOO_MANY_COLUMNS),
7468                                          errmsg("cannot have more than %d keys in a foreign key",
7469                                                         INDEX_MAX_KEYS)));
7470                 attnums[attnum] = ((Form_pg_attribute) GETSTRUCT(atttuple))->attnum;
7471                 atttypids[attnum] = ((Form_pg_attribute) GETSTRUCT(atttuple))->atttypid;
7472                 ReleaseSysCache(atttuple);
7473                 attnum++;
7474         }
7475
7476         return attnum;
7477 }
7478
7479 /*
7480  * transformFkeyGetPrimaryKey -
7481  *
7482  *      Look up the names, attnums, and types of the primary key attributes
7483  *      for the pkrel.  Also return the index OID and index opclasses of the
7484  *      index supporting the primary key.
7485  *
7486  *      All parameters except pkrel are output parameters.  Also, the function
7487  *      return value is the number of attributes in the primary key.
7488  *
7489  *      Used when the column list in the REFERENCES specification is omitted.
7490  */
7491 static int
7492 transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
7493                                                    List **attnamelist,
7494                                                    int16 *attnums, Oid *atttypids,
7495                                                    Oid *opclasses)
7496 {
7497         List       *indexoidlist;
7498         ListCell   *indexoidscan;
7499         HeapTuple       indexTuple = NULL;
7500         Form_pg_index indexStruct = NULL;
7501         Datum           indclassDatum;
7502         bool            isnull;
7503         oidvector  *indclass;
7504         int                     i;
7505
7506         /*
7507          * Get the list of index OIDs for the table from the relcache, and look up
7508          * each one in the pg_index syscache until we find one marked primary key
7509          * (hopefully there isn't more than one such).  Insist it's valid, too.
7510          */
7511         *indexOid = InvalidOid;
7512
7513         indexoidlist = RelationGetIndexList(pkrel);
7514
7515         foreach(indexoidscan, indexoidlist)
7516         {
7517                 Oid                     indexoid = lfirst_oid(indexoidscan);
7518
7519                 indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
7520                 if (!HeapTupleIsValid(indexTuple))
7521                         elog(ERROR, "cache lookup failed for index %u", indexoid);
7522                 indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
7523                 if (indexStruct->indisprimary && IndexIsValid(indexStruct))
7524                 {
7525                         /*
7526                          * Refuse to use a deferrable primary key.  This is per SQL spec,
7527                          * and there would be a lot of interesting semantic problems if we
7528                          * tried to allow it.
7529                          */
7530                         if (!indexStruct->indimmediate)
7531                                 ereport(ERROR,
7532                                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
7533                                                  errmsg("cannot use a deferrable primary key for referenced table \"%s\"",
7534                                                                 RelationGetRelationName(pkrel))));
7535
7536                         *indexOid = indexoid;
7537                         break;
7538                 }
7539                 ReleaseSysCache(indexTuple);
7540         }
7541
7542         list_free(indexoidlist);
7543
7544         /*
7545          * Check that we found it
7546          */
7547         if (!OidIsValid(*indexOid))
7548                 ereport(ERROR,
7549                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
7550                                  errmsg("there is no primary key for referenced table \"%s\"",
7551                                                 RelationGetRelationName(pkrel))));
7552
7553         /* Must get indclass the hard way */
7554         indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
7555                                                                         Anum_pg_index_indclass, &isnull);
7556         Assert(!isnull);
7557         indclass = (oidvector *) DatumGetPointer(indclassDatum);
7558
7559         /*
7560          * Now build the list of PK attributes from the indkey definition (we
7561          * assume a primary key cannot have expressional elements)
7562          */
7563         *attnamelist = NIL;
7564         for (i = 0; i < indexStruct->indnatts; i++)
7565         {
7566                 int                     pkattno = indexStruct->indkey.values[i];
7567
7568                 attnums[i] = pkattno;
7569                 atttypids[i] = attnumTypeId(pkrel, pkattno);
7570                 opclasses[i] = indclass->values[i];
7571                 *attnamelist = lappend(*attnamelist,
7572                            makeString(pstrdup(NameStr(*attnumAttName(pkrel, pkattno)))));
7573         }
7574
7575         ReleaseSysCache(indexTuple);
7576
7577         return i;
7578 }
7579
7580 /*
7581  * transformFkeyCheckAttrs -
7582  *
7583  *      Make sure that the attributes of a referenced table belong to a unique
7584  *      (or primary key) constraint.  Return the OID of the index supporting
7585  *      the constraint, as well as the opclasses associated with the index
7586  *      columns.
7587  */
7588 static Oid
7589 transformFkeyCheckAttrs(Relation pkrel,
7590                                                 int numattrs, int16 *attnums,
7591                                                 Oid *opclasses) /* output parameter */
7592 {
7593         Oid                     indexoid = InvalidOid;
7594         bool            found = false;
7595         bool            found_deferrable = false;
7596         List       *indexoidlist;
7597         ListCell   *indexoidscan;
7598         int                     i,
7599                                 j;
7600
7601         /*
7602          * Reject duplicate appearances of columns in the referenced-columns list.
7603          * Such a case is forbidden by the SQL standard, and even if we thought it
7604          * useful to allow it, there would be ambiguity about how to match the
7605          * list to unique indexes (in particular, it'd be unclear which index
7606          * opclass goes with which FK column).
7607          */
7608         for (i = 0; i < numattrs; i++)
7609         {
7610                 for (j = i + 1; j < numattrs; j++)
7611                 {
7612                         if (attnums[i] == attnums[j])
7613                                 ereport(ERROR,
7614                                                 (errcode(ERRCODE_INVALID_FOREIGN_KEY),
7615                                                  errmsg("foreign key referenced-columns list must not contain duplicates")));
7616                 }
7617         }
7618
7619         /*
7620          * Get the list of index OIDs for the table from the relcache, and look up
7621          * each one in the pg_index syscache, and match unique indexes to the list
7622          * of attnums we are given.
7623          */
7624         indexoidlist = RelationGetIndexList(pkrel);
7625
7626         foreach(indexoidscan, indexoidlist)
7627         {
7628                 HeapTuple       indexTuple;
7629                 Form_pg_index indexStruct;
7630
7631                 indexoid = lfirst_oid(indexoidscan);
7632                 indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
7633                 if (!HeapTupleIsValid(indexTuple))
7634                         elog(ERROR, "cache lookup failed for index %u", indexoid);
7635                 indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
7636
7637                 /*
7638                  * Must have the right number of columns; must be unique and not a
7639                  * partial index; forget it if there are any expressions, too. Invalid
7640                  * indexes are out as well.
7641                  */
7642                 if (indexStruct->indnatts == numattrs &&
7643                         indexStruct->indisunique &&
7644                         IndexIsValid(indexStruct) &&
7645                         heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
7646                         heap_attisnull(indexTuple, Anum_pg_index_indexprs))
7647                 {
7648                         Datum           indclassDatum;
7649                         bool            isnull;
7650                         oidvector  *indclass;
7651
7652                         /* Must get indclass the hard way */
7653                         indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
7654                                                                                         Anum_pg_index_indclass, &isnull);
7655                         Assert(!isnull);
7656                         indclass = (oidvector *) DatumGetPointer(indclassDatum);
7657
7658                         /*
7659                          * The given attnum list may match the index columns in any order.
7660                          * Check for a match, and extract the appropriate opclasses while
7661                          * we're at it.
7662                          *
7663                          * We know that attnums[] is duplicate-free per the test at the
7664                          * start of this function, and we checked above that the number of
7665                          * index columns agrees, so if we find a match for each attnums[]
7666                          * entry then we must have a one-to-one match in some order.
7667                          */
7668                         for (i = 0; i < numattrs; i++)
7669                         {
7670                                 found = false;
7671                                 for (j = 0; j < numattrs; j++)
7672                                 {
7673                                         if (attnums[i] == indexStruct->indkey.values[j])
7674                                         {
7675                                                 opclasses[i] = indclass->values[j];
7676                                                 found = true;
7677                                                 break;
7678                                         }
7679                                 }
7680                                 if (!found)
7681                                         break;
7682                         }
7683
7684                         /*
7685                          * Refuse to use a deferrable unique/primary key.  This is per SQL
7686                          * spec, and there would be a lot of interesting semantic problems
7687                          * if we tried to allow it.
7688                          */
7689                         if (found && !indexStruct->indimmediate)
7690                         {
7691                                 /*
7692                                  * Remember that we found an otherwise matching index, so that
7693                                  * we can generate a more appropriate error message.
7694                                  */
7695                                 found_deferrable = true;
7696                                 found = false;
7697                         }
7698                 }
7699                 ReleaseSysCache(indexTuple);
7700                 if (found)
7701                         break;
7702         }
7703
7704         if (!found)
7705         {
7706                 if (found_deferrable)
7707                         ereport(ERROR,
7708                                         (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
7709                                          errmsg("cannot use a deferrable unique constraint for referenced table \"%s\"",
7710                                                         RelationGetRelationName(pkrel))));
7711                 else
7712                         ereport(ERROR,
7713                                         (errcode(ERRCODE_INVALID_FOREIGN_KEY),
7714                                          errmsg("there is no unique constraint matching given keys for referenced table \"%s\"",
7715                                                         RelationGetRelationName(pkrel))));
7716         }
7717
7718         list_free(indexoidlist);
7719
7720         return indexoid;
7721 }
7722
7723 /*
7724  * findFkeyCast -
7725  *
7726  *      Wrapper around find_coercion_pathway() for ATAddForeignKeyConstraint().
7727  *      Caller has equal regard for binary coercibility and for an exact match.
7728 */
7729 static CoercionPathType
7730 findFkeyCast(Oid targetTypeId, Oid sourceTypeId, Oid *funcid)
7731 {
7732         CoercionPathType ret;
7733
7734         if (targetTypeId == sourceTypeId)
7735         {
7736                 ret = COERCION_PATH_RELABELTYPE;
7737                 *funcid = InvalidOid;
7738         }
7739         else
7740         {
7741                 ret = find_coercion_pathway(targetTypeId, sourceTypeId,
7742                                                                         COERCION_IMPLICIT, funcid);
7743                 if (ret == COERCION_PATH_NONE)
7744                         /* A previously-relied-upon cast is now gone. */
7745                         elog(ERROR, "could not find cast from %u to %u",
7746                                  sourceTypeId, targetTypeId);
7747         }
7748
7749         return ret;
7750 }
7751
7752 /* Permissions checks for ADD FOREIGN KEY */
7753 static void
7754 checkFkeyPermissions(Relation rel, int16 *attnums, int natts)
7755 {
7756         Oid                     roleid = GetUserId();
7757         AclResult       aclresult;
7758         int                     i;
7759
7760         /* Okay if we have relation-level REFERENCES permission */
7761         aclresult = pg_class_aclcheck(RelationGetRelid(rel), roleid,
7762                                                                   ACL_REFERENCES);
7763         if (aclresult == ACLCHECK_OK)
7764                 return;
7765         /* Else we must have REFERENCES on each column */
7766         for (i = 0; i < natts; i++)
7767         {
7768                 aclresult = pg_attribute_aclcheck(RelationGetRelid(rel), attnums[i],
7769                                                                                   roleid, ACL_REFERENCES);
7770                 if (aclresult != ACLCHECK_OK)
7771                         aclcheck_error(aclresult, ACL_KIND_CLASS,
7772                                                    RelationGetRelationName(rel));
7773         }
7774 }
7775
7776 /*
7777  * Scan the existing rows in a table to verify they meet a proposed
7778  * CHECK constraint.
7779  *
7780  * The caller must have opened and locked the relation appropriately.
7781  */
7782 static void
7783 validateCheckConstraint(Relation rel, HeapTuple constrtup)
7784 {
7785         EState     *estate;
7786         Datum           val;
7787         char       *conbin;
7788         Expr       *origexpr;
7789         List       *exprstate;
7790         TupleDesc       tupdesc;
7791         HeapScanDesc scan;
7792         HeapTuple       tuple;
7793         ExprContext *econtext;
7794         MemoryContext oldcxt;
7795         TupleTableSlot *slot;
7796         Form_pg_constraint constrForm;
7797         bool            isnull;
7798         Snapshot        snapshot;
7799
7800         /* VALIDATE CONSTRAINT is a no-op for foreign tables */
7801         if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
7802                 return;
7803
7804         constrForm = (Form_pg_constraint) GETSTRUCT(constrtup);
7805
7806         estate = CreateExecutorState();
7807
7808         /*
7809          * XXX this tuple doesn't really come from a syscache, but this doesn't
7810          * matter to SysCacheGetAttr, because it only wants to be able to fetch
7811          * the tupdesc
7812          */
7813         val = SysCacheGetAttr(CONSTROID, constrtup, Anum_pg_constraint_conbin,
7814                                                   &isnull);
7815         if (isnull)
7816                 elog(ERROR, "null conbin for constraint %u",
7817                          HeapTupleGetOid(constrtup));
7818         conbin = TextDatumGetCString(val);
7819         origexpr = (Expr *) stringToNode(conbin);
7820         exprstate = (List *)
7821                 ExecPrepareExpr((Expr *) make_ands_implicit(origexpr), estate);
7822
7823         econtext = GetPerTupleExprContext(estate);
7824         tupdesc = RelationGetDescr(rel);
7825         slot = MakeSingleTupleTableSlot(tupdesc);
7826         econtext->ecxt_scantuple = slot;
7827
7828         snapshot = RegisterSnapshot(GetLatestSnapshot());
7829         scan = heap_beginscan(rel, snapshot, 0, NULL);
7830
7831         /*
7832          * Switch to per-tuple memory context and reset it for each tuple
7833          * produced, so we don't leak memory.
7834          */
7835         oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
7836
7837         while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
7838         {
7839                 ExecStoreTuple(tuple, slot, InvalidBuffer, false);
7840
7841                 if (!ExecQual(exprstate, econtext, true))
7842                         ereport(ERROR,
7843                                         (errcode(ERRCODE_CHECK_VIOLATION),
7844                                          errmsg("check constraint \"%s\" is violated by some row",
7845                                                         NameStr(constrForm->conname)),
7846                                          errtableconstraint(rel, NameStr(constrForm->conname))));
7847
7848                 ResetExprContext(econtext);
7849         }
7850
7851         MemoryContextSwitchTo(oldcxt);
7852         heap_endscan(scan);
7853         UnregisterSnapshot(snapshot);
7854         ExecDropSingleTupleTableSlot(slot);
7855         FreeExecutorState(estate);
7856 }
7857
7858 /*
7859  * Scan the existing rows in a table to verify they meet a proposed FK
7860  * constraint.
7861  *
7862  * Caller must have opened and locked both relations appropriately.
7863  */
7864 static void
7865 validateForeignKeyConstraint(char *conname,
7866                                                          Relation rel,
7867                                                          Relation pkrel,
7868                                                          Oid pkindOid,
7869                                                          Oid constraintOid)
7870 {
7871         HeapScanDesc scan;
7872         HeapTuple       tuple;
7873         Trigger         trig;
7874         Snapshot        snapshot;
7875
7876         ereport(DEBUG1,
7877                         (errmsg("validating foreign key constraint \"%s\"", conname)));
7878
7879         /*
7880          * Build a trigger call structure; we'll need it either way.
7881          */
7882         MemSet(&trig, 0, sizeof(trig));
7883         trig.tgoid = InvalidOid;
7884         trig.tgname = conname;
7885         trig.tgenabled = TRIGGER_FIRES_ON_ORIGIN;
7886         trig.tgisinternal = TRUE;
7887         trig.tgconstrrelid = RelationGetRelid(pkrel);
7888         trig.tgconstrindid = pkindOid;
7889         trig.tgconstraint = constraintOid;
7890         trig.tgdeferrable = FALSE;
7891         trig.tginitdeferred = FALSE;
7892         /* we needn't fill in remaining fields */
7893
7894         /*
7895          * See if we can do it with a single LEFT JOIN query.  A FALSE result
7896          * indicates we must proceed with the fire-the-trigger method.
7897          */
7898         if (RI_Initial_Check(&trig, rel, pkrel))
7899                 return;
7900
7901         /*
7902          * Scan through each tuple, calling RI_FKey_check_ins (insert trigger) as
7903          * if that tuple had just been inserted.  If any of those fail, it should
7904          * ereport(ERROR) and that's that.
7905          */
7906         snapshot = RegisterSnapshot(GetLatestSnapshot());
7907         scan = heap_beginscan(rel, snapshot, 0, NULL);
7908
7909         while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
7910         {
7911                 FunctionCallInfoData fcinfo;
7912                 TriggerData trigdata;
7913
7914                 /*
7915                  * Make a call to the trigger function
7916                  *
7917                  * No parameters are passed, but we do set a context
7918                  */
7919                 MemSet(&fcinfo, 0, sizeof(fcinfo));
7920
7921                 /*
7922                  * We assume RI_FKey_check_ins won't look at flinfo...
7923                  */
7924                 trigdata.type = T_TriggerData;
7925                 trigdata.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW;
7926                 trigdata.tg_relation = rel;
7927                 trigdata.tg_trigtuple = tuple;
7928                 trigdata.tg_newtuple = NULL;
7929                 trigdata.tg_trigger = &trig;
7930                 trigdata.tg_trigtuplebuf = scan->rs_cbuf;
7931                 trigdata.tg_newtuplebuf = InvalidBuffer;
7932
7933                 fcinfo.context = (Node *) &trigdata;
7934
7935                 RI_FKey_check_ins(&fcinfo);
7936         }
7937
7938         heap_endscan(scan);
7939         UnregisterSnapshot(snapshot);
7940 }
7941
7942 static void
7943 CreateFKCheckTrigger(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint,
7944                                          Oid constraintOid, Oid indexOid, bool on_insert)
7945 {
7946         CreateTrigStmt *fk_trigger;
7947
7948         /*
7949          * Note: for a self-referential FK (referencing and referenced tables are
7950          * the same), it is important that the ON UPDATE action fires before the
7951          * CHECK action, since both triggers will fire on the same row during an
7952          * UPDATE event; otherwise the CHECK trigger will be checking a non-final
7953          * state of the row.  Triggers fire in name order, so we ensure this by
7954          * using names like "RI_ConstraintTrigger_a_NNNN" for the action triggers
7955          * and "RI_ConstraintTrigger_c_NNNN" for the check triggers.
7956          */
7957         fk_trigger = makeNode(CreateTrigStmt);
7958         fk_trigger->trigname = "RI_ConstraintTrigger_c";
7959         fk_trigger->relation = NULL;
7960         fk_trigger->row = true;
7961         fk_trigger->timing = TRIGGER_TYPE_AFTER;
7962
7963         /* Either ON INSERT or ON UPDATE */
7964         if (on_insert)
7965         {
7966                 fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins");
7967                 fk_trigger->events = TRIGGER_TYPE_INSERT;
7968         }
7969         else
7970         {
7971                 fk_trigger->funcname = SystemFuncName("RI_FKey_check_upd");
7972                 fk_trigger->events = TRIGGER_TYPE_UPDATE;
7973         }
7974
7975         fk_trigger->columns = NIL;
7976         fk_trigger->transitionRels = NIL;
7977         fk_trigger->whenClause = NULL;
7978         fk_trigger->isconstraint = true;
7979         fk_trigger->deferrable = fkconstraint->deferrable;
7980         fk_trigger->initdeferred = fkconstraint->initdeferred;
7981         fk_trigger->constrrel = NULL;
7982         fk_trigger->args = NIL;
7983
7984         (void) CreateTrigger(fk_trigger, NULL, myRelOid, refRelOid, constraintOid,
7985                                                  indexOid, true);
7986
7987         /* Make changes-so-far visible */
7988         CommandCounterIncrement();
7989 }
7990
7991 /*
7992  * Create the triggers that implement an FK constraint.
7993  *
7994  * NB: if you change any trigger properties here, see also
7995  * ATExecAlterConstraint.
7996  */
7997 static void
7998 createForeignKeyTriggers(Relation rel, Oid refRelOid, Constraint *fkconstraint,
7999                                                  Oid constraintOid, Oid indexOid)
8000 {
8001         Oid                     myRelOid;
8002         CreateTrigStmt *fk_trigger;
8003
8004         myRelOid = RelationGetRelid(rel);
8005
8006         /* Make changes-so-far visible */
8007         CommandCounterIncrement();
8008
8009         /*
8010          * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
8011          * DELETE action on the referenced table.
8012          */
8013         fk_trigger = makeNode(CreateTrigStmt);
8014         fk_trigger->trigname = "RI_ConstraintTrigger_a";
8015         fk_trigger->relation = NULL;
8016         fk_trigger->row = true;
8017         fk_trigger->timing = TRIGGER_TYPE_AFTER;
8018         fk_trigger->events = TRIGGER_TYPE_DELETE;
8019         fk_trigger->columns = NIL;
8020         fk_trigger->transitionRels = NIL;
8021         fk_trigger->whenClause = NULL;
8022         fk_trigger->isconstraint = true;
8023         fk_trigger->constrrel = NULL;
8024         switch (fkconstraint->fk_del_action)
8025         {
8026                 case FKCONSTR_ACTION_NOACTION:
8027                         fk_trigger->deferrable = fkconstraint->deferrable;
8028                         fk_trigger->initdeferred = fkconstraint->initdeferred;
8029                         fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_del");
8030                         break;
8031                 case FKCONSTR_ACTION_RESTRICT:
8032                         fk_trigger->deferrable = false;
8033                         fk_trigger->initdeferred = false;
8034                         fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_del");
8035                         break;
8036                 case FKCONSTR_ACTION_CASCADE:
8037                         fk_trigger->deferrable = false;
8038                         fk_trigger->initdeferred = false;
8039                         fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_del");
8040                         break;
8041                 case FKCONSTR_ACTION_SETNULL:
8042                         fk_trigger->deferrable = false;
8043                         fk_trigger->initdeferred = false;
8044                         fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_del");
8045                         break;
8046                 case FKCONSTR_ACTION_SETDEFAULT:
8047                         fk_trigger->deferrable = false;
8048                         fk_trigger->initdeferred = false;
8049                         fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_del");
8050                         break;
8051                 default:
8052                         elog(ERROR, "unrecognized FK action type: %d",
8053                                  (int) fkconstraint->fk_del_action);
8054                         break;
8055         }
8056         fk_trigger->args = NIL;
8057
8058         (void) CreateTrigger(fk_trigger, NULL, refRelOid, myRelOid, constraintOid,
8059                                                  indexOid, true);
8060
8061         /* Make changes-so-far visible */
8062         CommandCounterIncrement();
8063
8064         /*
8065          * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
8066          * UPDATE action on the referenced table.
8067          */
8068         fk_trigger = makeNode(CreateTrigStmt);
8069         fk_trigger->trigname = "RI_ConstraintTrigger_a";
8070         fk_trigger->relation = NULL;
8071         fk_trigger->row = true;
8072         fk_trigger->timing = TRIGGER_TYPE_AFTER;
8073         fk_trigger->events = TRIGGER_TYPE_UPDATE;
8074         fk_trigger->columns = NIL;
8075         fk_trigger->transitionRels = NIL;
8076         fk_trigger->whenClause = NULL;
8077         fk_trigger->isconstraint = true;
8078         fk_trigger->constrrel = NULL;
8079         switch (fkconstraint->fk_upd_action)
8080         {
8081                 case FKCONSTR_ACTION_NOACTION:
8082                         fk_trigger->deferrable = fkconstraint->deferrable;
8083                         fk_trigger->initdeferred = fkconstraint->initdeferred;
8084                         fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_upd");
8085                         break;
8086                 case FKCONSTR_ACTION_RESTRICT:
8087                         fk_trigger->deferrable = false;
8088                         fk_trigger->initdeferred = false;
8089                         fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_upd");
8090                         break;
8091                 case FKCONSTR_ACTION_CASCADE:
8092                         fk_trigger->deferrable = false;
8093                         fk_trigger->initdeferred = false;
8094                         fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_upd");
8095                         break;
8096                 case FKCONSTR_ACTION_SETNULL:
8097                         fk_trigger->deferrable = false;
8098                         fk_trigger->initdeferred = false;
8099                         fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_upd");
8100                         break;
8101                 case FKCONSTR_ACTION_SETDEFAULT:
8102                         fk_trigger->deferrable = false;
8103                         fk_trigger->initdeferred = false;
8104                         fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_upd");
8105                         break;
8106                 default:
8107                         elog(ERROR, "unrecognized FK action type: %d",
8108                                  (int) fkconstraint->fk_upd_action);
8109                         break;
8110         }
8111         fk_trigger->args = NIL;
8112
8113         (void) CreateTrigger(fk_trigger, NULL, refRelOid, myRelOid, constraintOid,
8114                                                  indexOid, true);
8115
8116         /* Make changes-so-far visible */
8117         CommandCounterIncrement();
8118
8119         /*
8120          * Build and execute CREATE CONSTRAINT TRIGGER statements for the CHECK
8121          * action for both INSERTs and UPDATEs on the referencing table.
8122          */
8123         CreateFKCheckTrigger(myRelOid, refRelOid, fkconstraint, constraintOid,
8124                                                  indexOid, true);
8125         CreateFKCheckTrigger(myRelOid, refRelOid, fkconstraint, constraintOid,
8126                                                  indexOid, false);
8127 }
8128
8129 /*
8130  * ALTER TABLE DROP CONSTRAINT
8131  *
8132  * Like DROP COLUMN, we can't use the normal ALTER TABLE recursion mechanism.
8133  */
8134 static void
8135 ATExecDropConstraint(Relation rel, const char *constrName,
8136                                          DropBehavior behavior,
8137                                          bool recurse, bool recursing,
8138                                          bool missing_ok, LOCKMODE lockmode)
8139 {
8140         List       *children;
8141         ListCell   *child;
8142         Relation        conrel;
8143         Form_pg_constraint con;
8144         SysScanDesc scan;
8145         ScanKeyData key;
8146         HeapTuple       tuple;
8147         bool            found = false;
8148         bool            is_no_inherit_constraint = false;
8149
8150         /* At top level, permission check was done in ATPrepCmd, else do it */
8151         if (recursing)
8152                 ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
8153
8154         conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
8155
8156         /*
8157          * Find and drop the target constraint
8158          */
8159         ScanKeyInit(&key,
8160                                 Anum_pg_constraint_conrelid,
8161                                 BTEqualStrategyNumber, F_OIDEQ,
8162                                 ObjectIdGetDatum(RelationGetRelid(rel)));
8163         scan = systable_beginscan(conrel, ConstraintRelidIndexId,
8164                                                           true, NULL, 1, &key);
8165
8166         while (HeapTupleIsValid(tuple = systable_getnext(scan)))
8167         {
8168                 ObjectAddress conobj;
8169
8170                 con = (Form_pg_constraint) GETSTRUCT(tuple);
8171
8172                 if (strcmp(NameStr(con->conname), constrName) != 0)
8173                         continue;
8174
8175                 /* Don't drop inherited constraints */
8176                 if (con->coninhcount > 0 && !recursing)
8177                         ereport(ERROR,
8178                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
8179                                          errmsg("cannot drop inherited constraint \"%s\" of relation \"%s\"",
8180                                                         constrName, RelationGetRelationName(rel))));
8181
8182                 is_no_inherit_constraint = con->connoinherit;
8183
8184                 /*
8185                  * If it's a foreign-key constraint, we'd better lock the referenced
8186                  * table and check that that's not in use, just as we've already done
8187                  * for the constrained table (else we might, eg, be dropping a trigger
8188                  * that has unfired events).  But we can/must skip that in the
8189                  * self-referential case.
8190                  */
8191                 if (con->contype == CONSTRAINT_FOREIGN &&
8192                         con->confrelid != RelationGetRelid(rel))
8193                 {
8194                         Relation        frel;
8195
8196                         /* Must match lock taken by RemoveTriggerById: */
8197                         frel = heap_open(con->confrelid, AccessExclusiveLock);
8198                         CheckTableNotInUse(frel, "ALTER TABLE");
8199                         heap_close(frel, NoLock);
8200                 }
8201
8202                 /*
8203                  * Perform the actual constraint deletion
8204                  */
8205                 conobj.classId = ConstraintRelationId;
8206                 conobj.objectId = HeapTupleGetOid(tuple);
8207                 conobj.objectSubId = 0;
8208
8209                 performDeletion(&conobj, behavior, 0);
8210
8211                 found = true;
8212
8213                 /* constraint found and dropped -- no need to keep looping */
8214                 break;
8215         }
8216
8217         systable_endscan(scan);
8218
8219         if (!found)
8220         {
8221                 if (!missing_ok)
8222                 {
8223                         ereport(ERROR,
8224                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
8225                                 errmsg("constraint \"%s\" of relation \"%s\" does not exist",
8226                                            constrName, RelationGetRelationName(rel))));
8227                 }
8228                 else
8229                 {
8230                         ereport(NOTICE,
8231                                         (errmsg("constraint \"%s\" of relation \"%s\" does not exist, skipping",
8232                                                         constrName, RelationGetRelationName(rel))));
8233                         heap_close(conrel, RowExclusiveLock);
8234                         return;
8235                 }
8236         }
8237
8238         /*
8239          * In case of a partitioned table, the constraint must be dropped from the
8240          * partitions too.  There is no such thing as NO INHERIT constraints in
8241          * case of partitioned tables.
8242          */
8243         if (!recurse && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
8244                 ereport(ERROR,
8245                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
8246                                  errmsg("constraint must be dropped from child tables too")));
8247
8248         /*
8249          * Propagate to children as appropriate.  Unlike most other ALTER
8250          * routines, we have to do this one level of recursion at a time; we can't
8251          * use find_all_inheritors to do it in one pass.
8252          */
8253         if (!is_no_inherit_constraint)
8254                 children = find_inheritance_children(RelationGetRelid(rel), lockmode);
8255         else
8256                 children = NIL;
8257
8258         foreach(child, children)
8259         {
8260                 Oid                     childrelid = lfirst_oid(child);
8261                 Relation        childrel;
8262                 HeapTuple       copy_tuple;
8263
8264                 /* find_inheritance_children already got lock */
8265                 childrel = heap_open(childrelid, NoLock);
8266                 CheckTableNotInUse(childrel, "ALTER TABLE");
8267
8268                 ScanKeyInit(&key,
8269                                         Anum_pg_constraint_conrelid,
8270                                         BTEqualStrategyNumber, F_OIDEQ,
8271                                         ObjectIdGetDatum(childrelid));
8272                 scan = systable_beginscan(conrel, ConstraintRelidIndexId,
8273                                                                   true, NULL, 1, &key);
8274
8275                 /* scan for matching tuple - there should only be one */
8276                 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
8277                 {
8278                         con = (Form_pg_constraint) GETSTRUCT(tuple);
8279
8280                         /* Right now only CHECK constraints can be inherited */
8281                         if (con->contype != CONSTRAINT_CHECK)
8282                                 continue;
8283
8284                         if (strcmp(NameStr(con->conname), constrName) == 0)
8285                                 break;
8286                 }
8287
8288                 if (!HeapTupleIsValid(tuple))
8289                         ereport(ERROR,
8290                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
8291                                 errmsg("constraint \"%s\" of relation \"%s\" does not exist",
8292                                            constrName,
8293                                            RelationGetRelationName(childrel))));
8294
8295                 copy_tuple = heap_copytuple(tuple);
8296
8297                 systable_endscan(scan);
8298
8299                 con = (Form_pg_constraint) GETSTRUCT(copy_tuple);
8300
8301                 if (con->coninhcount <= 0)              /* shouldn't happen */
8302                         elog(ERROR, "relation %u has non-inherited constraint \"%s\"",
8303                                  childrelid, constrName);
8304
8305                 if (recurse)
8306                 {
8307                         /*
8308                          * If the child constraint has other definition sources, just
8309                          * decrement its inheritance count; if not, recurse to delete it.
8310                          */
8311                         if (con->coninhcount == 1 && !con->conislocal)
8312                         {
8313                                 /* Time to delete this child constraint, too */
8314                                 ATExecDropConstraint(childrel, constrName, behavior,
8315                                                                          true, true,
8316                                                                          false, lockmode);
8317                         }
8318                         else
8319                         {
8320                                 /* Child constraint must survive my deletion */
8321                                 con->coninhcount--;
8322                                 CatalogTupleUpdate(conrel, &copy_tuple->t_self, copy_tuple);
8323
8324                                 /* Make update visible */
8325                                 CommandCounterIncrement();
8326                         }
8327                 }
8328                 else
8329                 {
8330                         /*
8331                          * If we were told to drop ONLY in this table (no recursion), we
8332                          * need to mark the inheritors' constraints as locally defined
8333                          * rather than inherited.
8334                          */
8335                         con->coninhcount--;
8336                         con->conislocal = true;
8337
8338                         CatalogTupleUpdate(conrel, &copy_tuple->t_self, copy_tuple);
8339
8340                         /* Make update visible */
8341                         CommandCounterIncrement();
8342                 }
8343
8344                 heap_freetuple(copy_tuple);
8345
8346                 heap_close(childrel, NoLock);
8347         }
8348
8349         heap_close(conrel, RowExclusiveLock);
8350 }
8351
8352 /*
8353  * ALTER COLUMN TYPE
8354  */
8355 static void
8356 ATPrepAlterColumnType(List **wqueue,
8357                                           AlteredTableInfo *tab, Relation rel,
8358                                           bool recurse, bool recursing,
8359                                           AlterTableCmd *cmd, LOCKMODE lockmode)
8360 {
8361         char       *colName = cmd->name;
8362         ColumnDef  *def = (ColumnDef *) cmd->def;
8363         TypeName   *typeName = def->typeName;
8364         Node       *transform = def->cooked_default;
8365         HeapTuple       tuple;
8366         Form_pg_attribute attTup;
8367         AttrNumber      attnum;
8368         Oid                     targettype;
8369         int32           targettypmod;
8370         Oid                     targetcollid;
8371         NewColumnValue *newval;
8372         ParseState *pstate = make_parsestate(NULL);
8373         AclResult       aclresult;
8374         bool            is_expr;
8375
8376         if (rel->rd_rel->reloftype && !recursing)
8377                 ereport(ERROR,
8378                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8379                                  errmsg("cannot alter column type of typed table")));
8380
8381         /* lookup the attribute so we can check inheritance status */
8382         tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
8383         if (!HeapTupleIsValid(tuple))
8384                 ereport(ERROR,
8385                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
8386                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
8387                                                 colName, RelationGetRelationName(rel))));
8388         attTup = (Form_pg_attribute) GETSTRUCT(tuple);
8389         attnum = attTup->attnum;
8390
8391         /* Can't alter a system attribute */
8392         if (attnum <= 0)
8393                 ereport(ERROR,
8394                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8395                                  errmsg("cannot alter system column \"%s\"",
8396                                                 colName)));
8397
8398         /* Don't alter inherited columns */
8399         if (attTup->attinhcount > 0 && !recursing)
8400                 ereport(ERROR,
8401                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
8402                                  errmsg("cannot alter inherited column \"%s\"",
8403                                                 colName)));
8404
8405         /* Don't alter columns used in the partition key */
8406         if (is_partition_attr(rel, attnum, &is_expr))
8407         {
8408                 if (!is_expr)
8409                         ereport(ERROR,
8410                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
8411                           errmsg("cannot alter type of column named in partition key")));
8412                 else
8413                         ereport(ERROR,
8414                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
8415                                          errmsg("cannot alter type of column referenced in partition key expression")));
8416         }
8417
8418         /* Look up the target type */
8419         typenameTypeIdAndMod(NULL, typeName, &targettype, &targettypmod);
8420
8421         aclresult = pg_type_aclcheck(targettype, GetUserId(), ACL_USAGE);
8422         if (aclresult != ACLCHECK_OK)
8423                 aclcheck_error_type(aclresult, targettype);
8424
8425         /* And the collation */
8426         targetcollid = GetColumnDefCollation(NULL, def, targettype);
8427
8428         /* make sure datatype is legal for a column */
8429         CheckAttributeType(colName, targettype, targetcollid,
8430                                            list_make1_oid(rel->rd_rel->reltype),
8431                                            false);
8432
8433         if (tab->relkind == RELKIND_RELATION ||
8434                 tab->relkind == RELKIND_PARTITIONED_TABLE)
8435         {
8436                 /*
8437                  * Set up an expression to transform the old data value to the new
8438                  * type. If a USING option was given, use the expression as
8439                  * transformed by transformAlterTableStmt, else just take the old
8440                  * value and try to coerce it.  We do this first so that type
8441                  * incompatibility can be detected before we waste effort, and because
8442                  * we need the expression to be parsed against the original table row
8443                  * type.
8444                  */
8445                 if (!transform)
8446                 {
8447                         transform = (Node *) makeVar(1, attnum,
8448                                                                                  attTup->atttypid, attTup->atttypmod,
8449                                                                                  attTup->attcollation,
8450                                                                                  0);
8451                 }
8452
8453                 transform = coerce_to_target_type(pstate,
8454                                                                                   transform, exprType(transform),
8455                                                                                   targettype, targettypmod,
8456                                                                                   COERCION_ASSIGNMENT,
8457                                                                                   COERCE_IMPLICIT_CAST,
8458                                                                                   -1);
8459                 if (transform == NULL)
8460                 {
8461                         /* error text depends on whether USING was specified or not */
8462                         if (def->cooked_default != NULL)
8463                                 ereport(ERROR,
8464                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
8465                                                  errmsg("result of USING clause for column \"%s\""
8466                                                                 " cannot be cast automatically to type %s",
8467                                                                 colName, format_type_be(targettype)),
8468                                                  errhint("You might need to add an explicit cast.")));
8469                         else
8470                                 ereport(ERROR,
8471                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
8472                                                  errmsg("column \"%s\" cannot be cast automatically to type %s",
8473                                                                 colName, format_type_be(targettype)),
8474                                 /* translator: USING is SQL, don't translate it */
8475                                            errhint("You might need to specify \"USING %s::%s\".",
8476                                                            quote_identifier(colName),
8477                                                            format_type_with_typemod(targettype,
8478                                                                                                                 targettypmod))));
8479                 }
8480
8481                 /* Fix collations after all else */
8482                 assign_expr_collations(pstate, transform);
8483
8484                 /* Plan the expr now so we can accurately assess the need to rewrite. */
8485                 transform = (Node *) expression_planner((Expr *) transform);
8486
8487                 /*
8488                  * Add a work queue item to make ATRewriteTable update the column
8489                  * contents.
8490                  */
8491                 newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
8492                 newval->attnum = attnum;
8493                 newval->expr = (Expr *) transform;
8494
8495                 tab->newvals = lappend(tab->newvals, newval);
8496                 if (ATColumnChangeRequiresRewrite(transform, attnum))
8497                         tab->rewrite |= AT_REWRITE_COLUMN_REWRITE;
8498         }
8499         else if (transform)
8500                 ereport(ERROR,
8501                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8502                                  errmsg("\"%s\" is not a table",
8503                                                 RelationGetRelationName(rel))));
8504
8505         if (tab->relkind == RELKIND_COMPOSITE_TYPE ||
8506                 tab->relkind == RELKIND_FOREIGN_TABLE)
8507         {
8508                 /*
8509                  * For composite types, do this check now.  Tables will check it later
8510                  * when the table is being rewritten.
8511                  */
8512                 find_composite_type_dependencies(rel->rd_rel->reltype, rel, NULL);
8513         }
8514
8515         ReleaseSysCache(tuple);
8516
8517         /*
8518          * Recurse manually by queueing a new command for each child, if
8519          * necessary. We cannot apply ATSimpleRecursion here because we need to
8520          * remap attribute numbers in the USING expression, if any.
8521          *
8522          * If we are told not to recurse, there had better not be any child
8523          * tables; else the alter would put them out of step.
8524          */
8525         if (recurse)
8526         {
8527                 Oid                     relid = RelationGetRelid(rel);
8528                 ListCell   *child;
8529                 List       *children;
8530
8531                 children = find_all_inheritors(relid, lockmode, NULL);
8532
8533                 /*
8534                  * find_all_inheritors does the recursive search of the inheritance
8535                  * hierarchy, so all we have to do is process all of the relids in the
8536                  * list that it returns.
8537                  */
8538                 foreach(child, children)
8539                 {
8540                         Oid                     childrelid = lfirst_oid(child);
8541                         Relation        childrel;
8542
8543                         if (childrelid == relid)
8544                                 continue;
8545
8546                         /* find_all_inheritors already got lock */
8547                         childrel = relation_open(childrelid, NoLock);
8548                         CheckTableNotInUse(childrel, "ALTER TABLE");
8549
8550                         /*
8551                          * Remap the attribute numbers.  If no USING expression was
8552                          * specified, there is no need for this step.
8553                          */
8554                         if (def->cooked_default)
8555                         {
8556                                 AttrNumber *attmap;
8557                                 bool            found_whole_row;
8558
8559                                 /* create a copy to scribble on */
8560                                 cmd = copyObject(cmd);
8561
8562                                 attmap = convert_tuples_by_name_map(RelationGetDescr(childrel),
8563                                                                                                         RelationGetDescr(rel),
8564                                                                  gettext_noop("could not convert row type"));
8565                                 ((ColumnDef *) cmd->def)->cooked_default =
8566                                         map_variable_attnos(def->cooked_default,
8567                                                                                 1, 0,
8568                                                                                 attmap, RelationGetDescr(rel)->natts,
8569                                                                                 &found_whole_row);
8570                                 if (found_whole_row)
8571                                         ereport(ERROR,
8572                                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8573                                                   errmsg("cannot convert whole-row table reference"),
8574                                                          errdetail("USING expression contains a whole-row table reference.")));
8575                                 pfree(attmap);
8576                         }
8577                         ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode);
8578                         relation_close(childrel, NoLock);
8579                 }
8580         }
8581         else if (!recursing &&
8582                          find_inheritance_children(RelationGetRelid(rel), NoLock) != NIL)
8583                 ereport(ERROR,
8584                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
8585                                  errmsg("type of inherited column \"%s\" must be changed in child tables too",
8586                                                 colName)));
8587
8588         if (tab->relkind == RELKIND_COMPOSITE_TYPE)
8589                 ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
8590 }
8591
8592 /*
8593  * When the data type of a column is changed, a rewrite might not be required
8594  * if the new type is sufficiently identical to the old one, and the USING
8595  * clause isn't trying to insert some other value.  It's safe to skip the
8596  * rewrite if the old type is binary coercible to the new type, or if the
8597  * new type is an unconstrained domain over the old type.  In the case of a
8598  * constrained domain, we could get by with scanning the table and checking
8599  * the constraint rather than actually rewriting it, but we don't currently
8600  * try to do that.
8601  */
8602 static bool
8603 ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno)
8604 {
8605         Assert(expr != NULL);
8606
8607         for (;;)
8608         {
8609                 /* only one varno, so no need to check that */
8610                 if (IsA(expr, Var) &&((Var *) expr)->varattno == varattno)
8611                         return false;
8612                 else if (IsA(expr, RelabelType))
8613                         expr = (Node *) ((RelabelType *) expr)->arg;
8614                 else if (IsA(expr, CoerceToDomain))
8615                 {
8616                         CoerceToDomain *d = (CoerceToDomain *) expr;
8617
8618                         if (DomainHasConstraints(d->resulttype))
8619                                 return true;
8620                         expr = (Node *) d->arg;
8621                 }
8622                 else
8623                         return true;
8624         }
8625 }
8626
8627 /*
8628  * ALTER COLUMN .. SET DATA TYPE
8629  *
8630  * Return the address of the modified column.
8631  */
8632 static ObjectAddress
8633 ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
8634                                           AlterTableCmd *cmd, LOCKMODE lockmode)
8635 {
8636         char       *colName = cmd->name;
8637         ColumnDef  *def = (ColumnDef *) cmd->def;
8638         TypeName   *typeName = def->typeName;
8639         HeapTuple       heapTup;
8640         Form_pg_attribute attTup;
8641         AttrNumber      attnum;
8642         HeapTuple       typeTuple;
8643         Form_pg_type tform;
8644         Oid                     targettype;
8645         int32           targettypmod;
8646         Oid                     targetcollid;
8647         Node       *defaultexpr;
8648         Relation        attrelation;
8649         Relation        depRel;
8650         ScanKeyData key[3];
8651         SysScanDesc scan;
8652         HeapTuple       depTup;
8653         ObjectAddress address;
8654
8655         attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
8656
8657         /* Look up the target column */
8658         heapTup = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
8659         if (!HeapTupleIsValid(heapTup))         /* shouldn't happen */
8660                 ereport(ERROR,
8661                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
8662                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
8663                                                 colName, RelationGetRelationName(rel))));
8664         attTup = (Form_pg_attribute) GETSTRUCT(heapTup);
8665         attnum = attTup->attnum;
8666
8667         /* Check for multiple ALTER TYPE on same column --- can't cope */
8668         if (attTup->atttypid != tab->oldDesc->attrs[attnum - 1]->atttypid ||
8669                 attTup->atttypmod != tab->oldDesc->attrs[attnum - 1]->atttypmod)
8670                 ereport(ERROR,
8671                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8672                                  errmsg("cannot alter type of column \"%s\" twice",
8673                                                 colName)));
8674
8675         /* Look up the target type (should not fail, since prep found it) */
8676         typeTuple = typenameType(NULL, typeName, &targettypmod);
8677         tform = (Form_pg_type) GETSTRUCT(typeTuple);
8678         targettype = HeapTupleGetOid(typeTuple);
8679         /* And the collation */
8680         targetcollid = GetColumnDefCollation(NULL, def, targettype);
8681
8682         /*
8683          * If there is a default expression for the column, get it and ensure we
8684          * can coerce it to the new datatype.  (We must do this before changing
8685          * the column type, because build_column_default itself will try to
8686          * coerce, and will not issue the error message we want if it fails.)
8687          *
8688          * We remove any implicit coercion steps at the top level of the old
8689          * default expression; this has been agreed to satisfy the principle of
8690          * least surprise.  (The conversion to the new column type should act like
8691          * it started from what the user sees as the stored expression, and the
8692          * implicit coercions aren't going to be shown.)
8693          */
8694         if (attTup->atthasdef)
8695         {
8696                 defaultexpr = build_column_default(rel, attnum);
8697                 Assert(defaultexpr);
8698                 defaultexpr = strip_implicit_coercions(defaultexpr);
8699                 defaultexpr = coerce_to_target_type(NULL,               /* no UNKNOWN params */
8700                                                                                   defaultexpr, exprType(defaultexpr),
8701                                                                                         targettype, targettypmod,
8702                                                                                         COERCION_ASSIGNMENT,
8703                                                                                         COERCE_IMPLICIT_CAST,
8704                                                                                         -1);
8705                 if (defaultexpr == NULL)
8706                         ereport(ERROR,
8707                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
8708                                          errmsg("default for column \"%s\" cannot be cast automatically to type %s",
8709                                                         colName, format_type_be(targettype))));
8710         }
8711         else
8712                 defaultexpr = NULL;
8713
8714         /*
8715          * Find everything that depends on the column (constraints, indexes, etc),
8716          * and record enough information to let us recreate the objects.
8717          *
8718          * The actual recreation does not happen here, but only after we have
8719          * performed all the individual ALTER TYPE operations.  We have to save
8720          * the info before executing ALTER TYPE, though, else the deparser will
8721          * get confused.
8722          *
8723          * There could be multiple entries for the same object, so we must check
8724          * to ensure we process each one only once.  Note: we assume that an index
8725          * that implements a constraint will not show a direct dependency on the
8726          * column.
8727          */
8728         depRel = heap_open(DependRelationId, RowExclusiveLock);
8729
8730         ScanKeyInit(&key[0],
8731                                 Anum_pg_depend_refclassid,
8732                                 BTEqualStrategyNumber, F_OIDEQ,
8733                                 ObjectIdGetDatum(RelationRelationId));
8734         ScanKeyInit(&key[1],
8735                                 Anum_pg_depend_refobjid,
8736                                 BTEqualStrategyNumber, F_OIDEQ,
8737                                 ObjectIdGetDatum(RelationGetRelid(rel)));
8738         ScanKeyInit(&key[2],
8739                                 Anum_pg_depend_refobjsubid,
8740                                 BTEqualStrategyNumber, F_INT4EQ,
8741                                 Int32GetDatum((int32) attnum));
8742
8743         scan = systable_beginscan(depRel, DependReferenceIndexId, true,
8744                                                           NULL, 3, key);
8745
8746         while (HeapTupleIsValid(depTup = systable_getnext(scan)))
8747         {
8748                 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(depTup);
8749                 ObjectAddress foundObject;
8750
8751                 /* We don't expect any PIN dependencies on columns */
8752                 if (foundDep->deptype == DEPENDENCY_PIN)
8753                         elog(ERROR, "cannot alter type of a pinned column");
8754
8755                 foundObject.classId = foundDep->classid;
8756                 foundObject.objectId = foundDep->objid;
8757                 foundObject.objectSubId = foundDep->objsubid;
8758
8759                 switch (getObjectClass(&foundObject))
8760                 {
8761                         case OCLASS_CLASS:
8762                                 {
8763                                         char            relKind = get_rel_relkind(foundObject.objectId);
8764
8765                                         if (relKind == RELKIND_INDEX)
8766                                         {
8767                                                 Assert(foundObject.objectSubId == 0);
8768                                                 if (!list_member_oid(tab->changedIndexOids, foundObject.objectId))
8769                                                 {
8770                                                         tab->changedIndexOids = lappend_oid(tab->changedIndexOids,
8771                                                                                                            foundObject.objectId);
8772                                                         tab->changedIndexDefs = lappend(tab->changedIndexDefs,
8773                                                            pg_get_indexdef_string(foundObject.objectId));
8774                                                 }
8775                                         }
8776                                         else if (relKind == RELKIND_SEQUENCE)
8777                                         {
8778                                                 /*
8779                                                  * This must be a SERIAL column's sequence.  We need
8780                                                  * not do anything to it.
8781                                                  */
8782                                                 Assert(foundObject.objectSubId == 0);
8783                                         }
8784                                         else
8785                                         {
8786                                                 /* Not expecting any other direct dependencies... */
8787                                                 elog(ERROR, "unexpected object depending on column: %s",
8788                                                          getObjectDescription(&foundObject));
8789                                         }
8790                                         break;
8791                                 }
8792
8793                         case OCLASS_CONSTRAINT:
8794                                 Assert(foundObject.objectSubId == 0);
8795                                 if (!list_member_oid(tab->changedConstraintOids,
8796                                                                          foundObject.objectId))
8797                                 {
8798                                         char       *defstring = pg_get_constraintdef_command(foundObject.objectId);
8799
8800                                         /*
8801                                          * Put NORMAL dependencies at the front of the list and
8802                                          * AUTO dependencies at the back.  This makes sure that
8803                                          * foreign-key constraints depending on this column will
8804                                          * be dropped before unique or primary-key constraints of
8805                                          * the column; which we must have because the FK
8806                                          * constraints depend on the indexes belonging to the
8807                                          * unique constraints.
8808                                          */
8809                                         if (foundDep->deptype == DEPENDENCY_NORMAL)
8810                                         {
8811                                                 tab->changedConstraintOids =
8812                                                         lcons_oid(foundObject.objectId,
8813                                                                           tab->changedConstraintOids);
8814                                                 tab->changedConstraintDefs =
8815                                                         lcons(defstring,
8816                                                                   tab->changedConstraintDefs);
8817                                         }
8818                                         else
8819                                         {
8820                                                 tab->changedConstraintOids =
8821                                                         lappend_oid(tab->changedConstraintOids,
8822                                                                                 foundObject.objectId);
8823                                                 tab->changedConstraintDefs =
8824                                                         lappend(tab->changedConstraintDefs,
8825                                                                         defstring);
8826                                         }
8827                                 }
8828                                 break;
8829
8830                         case OCLASS_REWRITE:
8831                                 /* XXX someday see if we can cope with revising views */
8832                                 ereport(ERROR,
8833                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8834                                                  errmsg("cannot alter type of a column used by a view or rule"),
8835                                                  errdetail("%s depends on column \"%s\"",
8836                                                                    getObjectDescription(&foundObject),
8837                                                                    colName)));
8838                                 break;
8839
8840                         case OCLASS_TRIGGER:
8841
8842                                 /*
8843                                  * A trigger can depend on a column because the column is
8844                                  * specified as an update target, or because the column is
8845                                  * used in the trigger's WHEN condition.  The first case would
8846                                  * not require any extra work, but the second case would
8847                                  * require updating the WHEN expression, which will take a
8848                                  * significant amount of new code.  Since we can't easily tell
8849                                  * which case applies, we punt for both.  FIXME someday.
8850                                  */
8851                                 ereport(ERROR,
8852                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8853                                                  errmsg("cannot alter type of a column used in a trigger definition"),
8854                                                  errdetail("%s depends on column \"%s\"",
8855                                                                    getObjectDescription(&foundObject),
8856                                                                    colName)));
8857                                 break;
8858
8859                         case OCLASS_POLICY:
8860
8861                                 /*
8862                                  * A policy can depend on a column because the column is
8863                                  * specified in the policy's USING or WITH CHECK qual
8864                                  * expressions.  It might be possible to rewrite and recheck
8865                                  * the policy expression, but punt for now.  It's certainly
8866                                  * easy enough to remove and recreate the policy; still, FIXME
8867                                  * someday.
8868                                  */
8869                                 ereport(ERROR,
8870                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8871                                                  errmsg("cannot alter type of a column used in a policy definition"),
8872                                                  errdetail("%s depends on column \"%s\"",
8873                                                                    getObjectDescription(&foundObject),
8874                                                                    colName)));
8875                                 break;
8876
8877                         case OCLASS_DEFAULT:
8878
8879                                 /*
8880                                  * Ignore the column's default expression, since we will fix
8881                                  * it below.
8882                                  */
8883                                 Assert(defaultexpr);
8884                                 break;
8885
8886                         case OCLASS_PROC:
8887                         case OCLASS_TYPE:
8888                         case OCLASS_CAST:
8889                         case OCLASS_COLLATION:
8890                         case OCLASS_CONVERSION:
8891                         case OCLASS_LANGUAGE:
8892                         case OCLASS_LARGEOBJECT:
8893                         case OCLASS_OPERATOR:
8894                         case OCLASS_OPCLASS:
8895                         case OCLASS_OPFAMILY:
8896                         case OCLASS_AMOP:
8897                         case OCLASS_AMPROC:
8898                         case OCLASS_SCHEMA:
8899                         case OCLASS_TSPARSER:
8900                         case OCLASS_TSDICT:
8901                         case OCLASS_TSTEMPLATE:
8902                         case OCLASS_TSCONFIG:
8903                         case OCLASS_ROLE:
8904                         case OCLASS_DATABASE:
8905                         case OCLASS_TBLSPACE:
8906                         case OCLASS_FDW:
8907                         case OCLASS_FOREIGN_SERVER:
8908                         case OCLASS_USER_MAPPING:
8909                         case OCLASS_DEFACL:
8910                         case OCLASS_EXTENSION:
8911
8912                                 /*
8913                                  * We don't expect any of these sorts of objects to depend on
8914                                  * a column.
8915                                  */
8916                                 elog(ERROR, "unexpected object depending on column: %s",
8917                                          getObjectDescription(&foundObject));
8918                                 break;
8919
8920                         default:
8921                                 elog(ERROR, "unrecognized object class: %u",
8922                                          foundObject.classId);
8923                 }
8924         }
8925
8926         systable_endscan(scan);
8927
8928         /*
8929          * Now scan for dependencies of this column on other things.  The only
8930          * thing we should find is the dependency on the column datatype, which we
8931          * want to remove, and possibly a collation dependency.
8932          */
8933         ScanKeyInit(&key[0],
8934                                 Anum_pg_depend_classid,
8935                                 BTEqualStrategyNumber, F_OIDEQ,
8936                                 ObjectIdGetDatum(RelationRelationId));
8937         ScanKeyInit(&key[1],
8938                                 Anum_pg_depend_objid,
8939                                 BTEqualStrategyNumber, F_OIDEQ,
8940                                 ObjectIdGetDatum(RelationGetRelid(rel)));
8941         ScanKeyInit(&key[2],
8942                                 Anum_pg_depend_objsubid,
8943                                 BTEqualStrategyNumber, F_INT4EQ,
8944                                 Int32GetDatum((int32) attnum));
8945
8946         scan = systable_beginscan(depRel, DependDependerIndexId, true,
8947                                                           NULL, 3, key);
8948
8949         while (HeapTupleIsValid(depTup = systable_getnext(scan)))
8950         {
8951                 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(depTup);
8952
8953                 if (foundDep->deptype != DEPENDENCY_NORMAL)
8954                         elog(ERROR, "found unexpected dependency type '%c'",
8955                                  foundDep->deptype);
8956                 if (!(foundDep->refclassid == TypeRelationId &&
8957                           foundDep->refobjid == attTup->atttypid) &&
8958                         !(foundDep->refclassid == CollationRelationId &&
8959                           foundDep->refobjid == attTup->attcollation))
8960                         elog(ERROR, "found unexpected dependency for column");
8961
8962                 CatalogTupleDelete(depRel, &depTup->t_self);
8963         }
8964
8965         systable_endscan(scan);
8966
8967         heap_close(depRel, RowExclusiveLock);
8968
8969         /*
8970          * Here we go --- change the recorded column type and collation.  (Note
8971          * heapTup is a copy of the syscache entry, so okay to scribble on.)
8972          */
8973         attTup->atttypid = targettype;
8974         attTup->atttypmod = targettypmod;
8975         attTup->attcollation = targetcollid;
8976         attTup->attndims = list_length(typeName->arrayBounds);
8977         attTup->attlen = tform->typlen;
8978         attTup->attbyval = tform->typbyval;
8979         attTup->attalign = tform->typalign;
8980         attTup->attstorage = tform->typstorage;
8981
8982         ReleaseSysCache(typeTuple);
8983
8984         CatalogTupleUpdate(attrelation, &heapTup->t_self, heapTup);
8985
8986         heap_close(attrelation, RowExclusiveLock);
8987
8988         /* Install dependencies on new datatype and collation */
8989         add_column_datatype_dependency(RelationGetRelid(rel), attnum, targettype);
8990         add_column_collation_dependency(RelationGetRelid(rel), attnum, targetcollid);
8991
8992         /*
8993          * Drop any pg_statistic entry for the column, since it's now wrong type
8994          */
8995         RemoveStatistics(RelationGetRelid(rel), attnum);
8996
8997         InvokeObjectPostAlterHook(RelationRelationId,
8998                                                           RelationGetRelid(rel), attnum);
8999
9000         /*
9001          * Update the default, if present, by brute force --- remove and re-add
9002          * the default.  Probably unsafe to take shortcuts, since the new version
9003          * may well have additional dependencies.  (It's okay to do this now,
9004          * rather than after other ALTER TYPE commands, since the default won't
9005          * depend on other column types.)
9006          */
9007         if (defaultexpr)
9008         {
9009                 /* Must make new row visible since it will be updated again */
9010                 CommandCounterIncrement();
9011
9012                 /*
9013                  * We use RESTRICT here for safety, but at present we do not expect
9014                  * anything to depend on the default.
9015                  */
9016                 RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true,
9017                                                   true);
9018
9019                 StoreAttrDefault(rel, attnum, defaultexpr, true);
9020         }
9021
9022         ObjectAddressSubSet(address, RelationRelationId,
9023                                                 RelationGetRelid(rel), attnum);
9024
9025         /* Cleanup */
9026         heap_freetuple(heapTup);
9027
9028         return address;
9029 }
9030
9031 /*
9032  * Returns the address of the modified column
9033  */
9034 static ObjectAddress
9035 ATExecAlterColumnGenericOptions(Relation rel,
9036                                                                 const char *colName,
9037                                                                 List *options,
9038                                                                 LOCKMODE lockmode)
9039 {
9040         Relation        ftrel;
9041         Relation        attrel;
9042         ForeignServer *server;
9043         ForeignDataWrapper *fdw;
9044         HeapTuple       tuple;
9045         HeapTuple       newtuple;
9046         bool            isnull;
9047         Datum           repl_val[Natts_pg_attribute];
9048         bool            repl_null[Natts_pg_attribute];
9049         bool            repl_repl[Natts_pg_attribute];
9050         Datum           datum;
9051         Form_pg_foreign_table fttableform;
9052         Form_pg_attribute atttableform;
9053         AttrNumber      attnum;
9054         ObjectAddress address;
9055
9056         if (options == NIL)
9057                 return InvalidObjectAddress;
9058
9059         /* First, determine FDW validator associated to the foreign table. */
9060         ftrel = heap_open(ForeignTableRelationId, AccessShareLock);
9061         tuple = SearchSysCache1(FOREIGNTABLEREL, rel->rd_id);
9062         if (!HeapTupleIsValid(tuple))
9063                 ereport(ERROR,
9064                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
9065                                  errmsg("foreign table \"%s\" does not exist",
9066                                                 RelationGetRelationName(rel))));
9067         fttableform = (Form_pg_foreign_table) GETSTRUCT(tuple);
9068         server = GetForeignServer(fttableform->ftserver);
9069         fdw = GetForeignDataWrapper(server->fdwid);
9070
9071         heap_close(ftrel, AccessShareLock);
9072         ReleaseSysCache(tuple);
9073
9074         attrel = heap_open(AttributeRelationId, RowExclusiveLock);
9075         tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
9076         if (!HeapTupleIsValid(tuple))
9077                 ereport(ERROR,
9078                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
9079                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
9080                                                 colName, RelationGetRelationName(rel))));
9081
9082         /* Prevent them from altering a system attribute */
9083         atttableform = (Form_pg_attribute) GETSTRUCT(tuple);
9084         attnum = atttableform->attnum;
9085         if (attnum <= 0)
9086                 ereport(ERROR,
9087                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9088                                  errmsg("cannot alter system column \"%s\"", colName)));
9089
9090
9091         /* Initialize buffers for new tuple values */
9092         memset(repl_val, 0, sizeof(repl_val));
9093         memset(repl_null, false, sizeof(repl_null));
9094         memset(repl_repl, false, sizeof(repl_repl));
9095
9096         /* Extract the current options */
9097         datum = SysCacheGetAttr(ATTNAME,
9098                                                         tuple,
9099                                                         Anum_pg_attribute_attfdwoptions,
9100                                                         &isnull);
9101         if (isnull)
9102                 datum = PointerGetDatum(NULL);
9103
9104         /* Transform the options */
9105         datum = transformGenericOptions(AttributeRelationId,
9106                                                                         datum,
9107                                                                         options,
9108                                                                         fdw->fdwvalidator);
9109
9110         if (PointerIsValid(DatumGetPointer(datum)))
9111                 repl_val[Anum_pg_attribute_attfdwoptions - 1] = datum;
9112         else
9113                 repl_null[Anum_pg_attribute_attfdwoptions - 1] = true;
9114
9115         repl_repl[Anum_pg_attribute_attfdwoptions - 1] = true;
9116
9117         /* Everything looks good - update the tuple */
9118
9119         newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrel),
9120                                                                  repl_val, repl_null, repl_repl);
9121
9122         CatalogTupleUpdate(attrel, &newtuple->t_self, newtuple);
9123
9124         InvokeObjectPostAlterHook(RelationRelationId,
9125                                                           RelationGetRelid(rel),
9126                                                           atttableform->attnum);
9127         ObjectAddressSubSet(address, RelationRelationId,
9128                                                 RelationGetRelid(rel), attnum);
9129
9130         ReleaseSysCache(tuple);
9131
9132         heap_close(attrel, RowExclusiveLock);
9133
9134         heap_freetuple(newtuple);
9135
9136         return address;
9137 }
9138
9139 /*
9140  * Cleanup after we've finished all the ALTER TYPE operations for a
9141  * particular relation.  We have to drop and recreate all the indexes
9142  * and constraints that depend on the altered columns.
9143  */
9144 static void
9145 ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
9146 {
9147         ObjectAddress obj;
9148         ListCell   *def_item;
9149         ListCell   *oid_item;
9150
9151         /*
9152          * Re-parse the index and constraint definitions, and attach them to the
9153          * appropriate work queue entries.  We do this before dropping because in
9154          * the case of a FOREIGN KEY constraint, we might not yet have exclusive
9155          * lock on the table the constraint is attached to, and we need to get
9156          * that before dropping.  It's safe because the parser won't actually look
9157          * at the catalogs to detect the existing entry.
9158          *
9159          * We can't rely on the output of deparsing to tell us which relation to
9160          * operate on, because concurrent activity might have made the name
9161          * resolve differently.  Instead, we've got to use the OID of the
9162          * constraint or index we're processing to figure out which relation to
9163          * operate on.
9164          */
9165         forboth(oid_item, tab->changedConstraintOids,
9166                         def_item, tab->changedConstraintDefs)
9167         {
9168                 Oid                     oldId = lfirst_oid(oid_item);
9169                 HeapTuple       tup;
9170                 Form_pg_constraint con;
9171                 Oid                     relid;
9172                 Oid                     confrelid;
9173                 bool            conislocal;
9174
9175                 tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(oldId));
9176                 if (!HeapTupleIsValid(tup))             /* should not happen */
9177                         elog(ERROR, "cache lookup failed for constraint %u", oldId);
9178                 con = (Form_pg_constraint) GETSTRUCT(tup);
9179                 relid = con->conrelid;
9180                 confrelid = con->confrelid;
9181                 conislocal = con->conislocal;
9182                 ReleaseSysCache(tup);
9183
9184                 /*
9185                  * If the constraint is inherited (only), we don't want to inject a
9186                  * new definition here; it'll get recreated when ATAddCheckConstraint
9187                  * recurses from adding the parent table's constraint.  But we had to
9188                  * carry the info this far so that we can drop the constraint below.
9189                  */
9190                 if (!conislocal)
9191                         continue;
9192
9193                 ATPostAlterTypeParse(oldId, relid, confrelid,
9194                                                          (char *) lfirst(def_item),
9195                                                          wqueue, lockmode, tab->rewrite);
9196         }
9197         forboth(oid_item, tab->changedIndexOids,
9198                         def_item, tab->changedIndexDefs)
9199         {
9200                 Oid                     oldId = lfirst_oid(oid_item);
9201                 Oid                     relid;
9202
9203                 relid = IndexGetRelation(oldId, false);
9204                 ATPostAlterTypeParse(oldId, relid, InvalidOid,
9205                                                          (char *) lfirst(def_item),
9206                                                          wqueue, lockmode, tab->rewrite);
9207         }
9208
9209         /*
9210          * Now we can drop the existing constraints and indexes --- constraints
9211          * first, since some of them might depend on the indexes.  In fact, we
9212          * have to delete FOREIGN KEY constraints before UNIQUE constraints, but
9213          * we already ordered the constraint list to ensure that would happen. It
9214          * should be okay to use DROP_RESTRICT here, since nothing else should be
9215          * depending on these objects.
9216          */
9217         foreach(oid_item, tab->changedConstraintOids)
9218         {
9219                 obj.classId = ConstraintRelationId;
9220                 obj.objectId = lfirst_oid(oid_item);
9221                 obj.objectSubId = 0;
9222                 performDeletion(&obj, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
9223         }
9224
9225         foreach(oid_item, tab->changedIndexOids)
9226         {
9227                 obj.classId = RelationRelationId;
9228                 obj.objectId = lfirst_oid(oid_item);
9229                 obj.objectSubId = 0;
9230                 performDeletion(&obj, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
9231         }
9232
9233         /*
9234          * The objects will get recreated during subsequent passes over the work
9235          * queue.
9236          */
9237 }
9238
9239 static void
9240 ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
9241                                          List **wqueue, LOCKMODE lockmode, bool rewrite)
9242 {
9243         List       *raw_parsetree_list;
9244         List       *querytree_list;
9245         ListCell   *list_item;
9246         Relation        rel;
9247
9248         /*
9249          * We expect that we will get only ALTER TABLE and CREATE INDEX
9250          * statements. Hence, there is no need to pass them through
9251          * parse_analyze() or the rewriter, but instead we need to pass them
9252          * through parse_utilcmd.c to make them ready for execution.
9253          */
9254         raw_parsetree_list = raw_parser(cmd);
9255         querytree_list = NIL;
9256         foreach(list_item, raw_parsetree_list)
9257         {
9258                 RawStmt    *rs = castNode(RawStmt, lfirst(list_item));
9259                 Node       *stmt = rs->stmt;
9260
9261                 if (IsA(stmt, IndexStmt))
9262                         querytree_list = lappend(querytree_list,
9263                                                                          transformIndexStmt(oldRelId,
9264                                                                                                                 (IndexStmt *) stmt,
9265                                                                                                                 cmd));
9266                 else if (IsA(stmt, AlterTableStmt))
9267                         querytree_list = list_concat(querytree_list,
9268                                                                                  transformAlterTableStmt(oldRelId,
9269                                                                                                          (AlterTableStmt *) stmt,
9270                                                                                                                                  cmd));
9271                 else
9272                         querytree_list = lappend(querytree_list, stmt);
9273         }
9274
9275         /* Caller should already have acquired whatever lock we need. */
9276         rel = relation_open(oldRelId, NoLock);
9277
9278         /*
9279          * Attach each generated command to the proper place in the work queue.
9280          * Note this could result in creation of entirely new work-queue entries.
9281          *
9282          * Also note that we have to tweak the command subtypes, because it turns
9283          * out that re-creation of indexes and constraints has to act a bit
9284          * differently from initial creation.
9285          */
9286         foreach(list_item, querytree_list)
9287         {
9288                 Node       *stm = (Node *) lfirst(list_item);
9289                 AlteredTableInfo *tab;
9290
9291                 tab = ATGetQueueEntry(wqueue, rel);
9292
9293                 if (IsA(stm, IndexStmt))
9294                 {
9295                         IndexStmt  *stmt = (IndexStmt *) stm;
9296                         AlterTableCmd *newcmd;
9297
9298                         if (!rewrite)
9299                                 TryReuseIndex(oldId, stmt);
9300                         /* keep the index's comment */
9301                         stmt->idxcomment = GetComment(oldId, RelationRelationId, 0);
9302
9303                         newcmd = makeNode(AlterTableCmd);
9304                         newcmd->subtype = AT_ReAddIndex;
9305                         newcmd->def = (Node *) stmt;
9306                         tab->subcmds[AT_PASS_OLD_INDEX] =
9307                                 lappend(tab->subcmds[AT_PASS_OLD_INDEX], newcmd);
9308                 }
9309                 else if (IsA(stm, AlterTableStmt))
9310                 {
9311                         AlterTableStmt *stmt = (AlterTableStmt *) stm;
9312                         ListCell   *lcmd;
9313
9314                         foreach(lcmd, stmt->cmds)
9315                         {
9316                                 AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
9317
9318                                 if (cmd->subtype == AT_AddIndex)
9319                                 {
9320                                         IndexStmt  *indstmt;
9321                                         Oid                     indoid;
9322
9323                                         indstmt = castNode(IndexStmt, cmd->def);
9324                                         indoid = get_constraint_index(oldId);
9325
9326                                         if (!rewrite)
9327                                                 TryReuseIndex(indoid, indstmt);
9328                                         /* keep any comment on the index */
9329                                         indstmt->idxcomment = GetComment(indoid,
9330                                                                                                          RelationRelationId, 0);
9331
9332                                         cmd->subtype = AT_ReAddIndex;
9333                                         tab->subcmds[AT_PASS_OLD_INDEX] =
9334                                                 lappend(tab->subcmds[AT_PASS_OLD_INDEX], cmd);
9335
9336                                         /* recreate any comment on the constraint */
9337                                         RebuildConstraintComment(tab,
9338                                                                                          AT_PASS_OLD_INDEX,
9339                                                                                          oldId,
9340                                                                                          rel, indstmt->idxname);
9341                                 }
9342                                 else if (cmd->subtype == AT_AddConstraint)
9343                                 {
9344                                         Constraint *con;
9345
9346                                         con = castNode(Constraint, cmd->def);
9347                                         con->old_pktable_oid = refRelId;
9348                                         /* rewriting neither side of a FK */
9349                                         if (con->contype == CONSTR_FOREIGN &&
9350                                                 !rewrite && tab->rewrite == 0)
9351                                                 TryReuseForeignKey(oldId, con);
9352                                         cmd->subtype = AT_ReAddConstraint;
9353                                         tab->subcmds[AT_PASS_OLD_CONSTR] =
9354                                                 lappend(tab->subcmds[AT_PASS_OLD_CONSTR], cmd);
9355
9356                                         /* recreate any comment on the constraint */
9357                                         RebuildConstraintComment(tab,
9358                                                                                          AT_PASS_OLD_CONSTR,
9359                                                                                          oldId,
9360                                                                                          rel, con->conname);
9361                                 }
9362                                 else
9363                                         elog(ERROR, "unexpected statement subtype: %d",
9364                                                  (int) cmd->subtype);
9365                         }
9366                 }
9367                 else
9368                         elog(ERROR, "unexpected statement type: %d",
9369                                  (int) nodeTag(stm));
9370         }
9371
9372         relation_close(rel, NoLock);
9373 }
9374
9375 /*
9376  * Subroutine for ATPostAlterTypeParse() to recreate a comment entry for
9377  * a constraint that is being re-added.
9378  */
9379 static void
9380 RebuildConstraintComment(AlteredTableInfo *tab, int pass, Oid objid,
9381                                                  Relation rel, char *conname)
9382 {
9383         CommentStmt *cmd;
9384         char       *comment_str;
9385         AlterTableCmd *newcmd;
9386
9387         /* Look for comment for object wanted, and leave if none */
9388         comment_str = GetComment(objid, ConstraintRelationId, 0);
9389         if (comment_str == NULL)
9390                 return;
9391
9392         /* Build node CommentStmt */
9393         cmd = makeNode(CommentStmt);
9394         cmd->objtype = OBJECT_TABCONSTRAINT;
9395         cmd->object = (Node *) list_make3(makeString(get_namespace_name(RelationGetNamespace(rel))),
9396                                                                           makeString(RelationGetRelationName(rel)),
9397                                                                           makeString(conname));
9398         cmd->comment = comment_str;
9399
9400         /* Append it to list of commands */
9401         newcmd = makeNode(AlterTableCmd);
9402         newcmd->subtype = AT_ReAddComment;
9403         newcmd->def = (Node *) cmd;
9404         tab->subcmds[pass] = lappend(tab->subcmds[pass], newcmd);
9405 }
9406
9407 /*
9408  * Subroutine for ATPostAlterTypeParse().  Calls out to CheckIndexCompatible()
9409  * for the real analysis, then mutates the IndexStmt based on that verdict.
9410  */
9411 static void
9412 TryReuseIndex(Oid oldId, IndexStmt *stmt)
9413 {
9414         if (CheckIndexCompatible(oldId,
9415                                                          stmt->accessMethod,
9416                                                          stmt->indexParams,
9417                                                          stmt->excludeOpNames))
9418         {
9419                 Relation        irel = index_open(oldId, NoLock);
9420
9421                 stmt->oldNode = irel->rd_node.relNode;
9422                 index_close(irel, NoLock);
9423         }
9424 }
9425
9426 /*
9427  * Subroutine for ATPostAlterTypeParse().
9428  *
9429  * Stash the old P-F equality operator into the Constraint node, for possible
9430  * use by ATAddForeignKeyConstraint() in determining whether revalidation of
9431  * this constraint can be skipped.
9432  */
9433 static void
9434 TryReuseForeignKey(Oid oldId, Constraint *con)
9435 {
9436         HeapTuple       tup;
9437         Datum           adatum;
9438         bool            isNull;
9439         ArrayType  *arr;
9440         Oid                *rawarr;
9441         int                     numkeys;
9442         int                     i;
9443
9444         Assert(con->contype == CONSTR_FOREIGN);
9445         Assert(con->old_conpfeqop == NIL);      /* already prepared this node */
9446
9447         tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(oldId));
9448         if (!HeapTupleIsValid(tup)) /* should not happen */
9449                 elog(ERROR, "cache lookup failed for constraint %u", oldId);
9450
9451         adatum = SysCacheGetAttr(CONSTROID, tup,
9452                                                          Anum_pg_constraint_conpfeqop, &isNull);
9453         if (isNull)
9454                 elog(ERROR, "null conpfeqop for constraint %u", oldId);
9455         arr = DatumGetArrayTypeP(adatum);       /* ensure not toasted */
9456         numkeys = ARR_DIMS(arr)[0];
9457         /* test follows the one in ri_FetchConstraintInfo() */
9458         if (ARR_NDIM(arr) != 1 ||
9459                 ARR_HASNULL(arr) ||
9460                 ARR_ELEMTYPE(arr) != OIDOID)
9461                 elog(ERROR, "conpfeqop is not a 1-D Oid array");
9462         rawarr = (Oid *) ARR_DATA_PTR(arr);
9463
9464         /* stash a List of the operator Oids in our Constraint node */
9465         for (i = 0; i < numkeys; i++)
9466                 con->old_conpfeqop = lcons_oid(rawarr[i], con->old_conpfeqop);
9467
9468         ReleaseSysCache(tup);
9469 }
9470
9471 /*
9472  * ALTER TABLE OWNER
9473  *
9474  * recursing is true if we are recursing from a table to its indexes,
9475  * sequences, or toast table.  We don't allow the ownership of those things to
9476  * be changed separately from the parent table.  Also, we can skip permission
9477  * checks (this is necessary not just an optimization, else we'd fail to
9478  * handle toast tables properly).
9479  *
9480  * recursing is also true if ALTER TYPE OWNER is calling us to fix up a
9481  * free-standing composite type.
9482  */
9483 void
9484 ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
9485 {
9486         Relation        target_rel;
9487         Relation        class_rel;
9488         HeapTuple       tuple;
9489         Form_pg_class tuple_class;
9490
9491         /*
9492          * Get exclusive lock till end of transaction on the target table. Use
9493          * relation_open so that we can work on indexes and sequences.
9494          */
9495         target_rel = relation_open(relationOid, lockmode);
9496
9497         /* Get its pg_class tuple, too */
9498         class_rel = heap_open(RelationRelationId, RowExclusiveLock);
9499
9500         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationOid));
9501         if (!HeapTupleIsValid(tuple))
9502                 elog(ERROR, "cache lookup failed for relation %u", relationOid);
9503         tuple_class = (Form_pg_class) GETSTRUCT(tuple);
9504
9505         /* Can we change the ownership of this tuple? */
9506         switch (tuple_class->relkind)
9507         {
9508                 case RELKIND_RELATION:
9509                 case RELKIND_VIEW:
9510                 case RELKIND_MATVIEW:
9511                 case RELKIND_FOREIGN_TABLE:
9512                 case RELKIND_PARTITIONED_TABLE:
9513                         /* ok to change owner */
9514                         break;
9515                 case RELKIND_INDEX:
9516                         if (!recursing)
9517                         {
9518                                 /*
9519                                  * Because ALTER INDEX OWNER used to be allowed, and in fact
9520                                  * is generated by old versions of pg_dump, we give a warning
9521                                  * and do nothing rather than erroring out.  Also, to avoid
9522                                  * unnecessary chatter while restoring those old dumps, say
9523                                  * nothing at all if the command would be a no-op anyway.
9524                                  */
9525                                 if (tuple_class->relowner != newOwnerId)
9526                                         ereport(WARNING,
9527                                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9528                                                          errmsg("cannot change owner of index \"%s\"",
9529                                                                         NameStr(tuple_class->relname)),
9530                                                          errhint("Change the ownership of the index's table, instead.")));
9531                                 /* quick hack to exit via the no-op path */
9532                                 newOwnerId = tuple_class->relowner;
9533                         }
9534                         break;
9535                 case RELKIND_SEQUENCE:
9536                         if (!recursing &&
9537                                 tuple_class->relowner != newOwnerId)
9538                         {
9539                                 /* if it's an owned sequence, disallow changing it by itself */
9540                                 Oid                     tableId;
9541                                 int32           colId;
9542
9543                                 if (sequenceIsOwned(relationOid, &tableId, &colId))
9544                                         ereport(ERROR,
9545                                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9546                                                          errmsg("cannot change owner of sequence \"%s\"",
9547                                                                         NameStr(tuple_class->relname)),
9548                                           errdetail("Sequence \"%s\" is linked to table \"%s\".",
9549                                                                 NameStr(tuple_class->relname),
9550                                                                 get_rel_name(tableId))));
9551                         }
9552                         break;
9553                 case RELKIND_COMPOSITE_TYPE:
9554                         if (recursing)
9555                                 break;
9556                         ereport(ERROR,
9557                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9558                                          errmsg("\"%s\" is a composite type",
9559                                                         NameStr(tuple_class->relname)),
9560                                          errhint("Use ALTER TYPE instead.")));
9561                         break;
9562                 case RELKIND_TOASTVALUE:
9563                         if (recursing)
9564                                 break;
9565                         /* FALL THRU */
9566                 default:
9567                         ereport(ERROR,
9568                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9569                         errmsg("\"%s\" is not a table, view, sequence, or foreign table",
9570                                    NameStr(tuple_class->relname))));
9571         }
9572
9573         /*
9574          * If the new owner is the same as the existing owner, consider the
9575          * command to have succeeded.  This is for dump restoration purposes.
9576          */
9577         if (tuple_class->relowner != newOwnerId)
9578         {
9579                 Datum           repl_val[Natts_pg_class];
9580                 bool            repl_null[Natts_pg_class];
9581                 bool            repl_repl[Natts_pg_class];
9582                 Acl                *newAcl;
9583                 Datum           aclDatum;
9584                 bool            isNull;
9585                 HeapTuple       newtuple;
9586
9587                 /* skip permission checks when recursing to index or toast table */
9588                 if (!recursing)
9589                 {
9590                         /* Superusers can always do it */
9591                         if (!superuser())
9592                         {
9593                                 Oid                     namespaceOid = tuple_class->relnamespace;
9594                                 AclResult       aclresult;
9595
9596                                 /* Otherwise, must be owner of the existing object */
9597                                 if (!pg_class_ownercheck(relationOid, GetUserId()))
9598                                         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
9599                                                                    RelationGetRelationName(target_rel));
9600
9601                                 /* Must be able to become new owner */
9602                                 check_is_member_of_role(GetUserId(), newOwnerId);
9603
9604                                 /* New owner must have CREATE privilege on namespace */
9605                                 aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
9606                                                                                                   ACL_CREATE);
9607                                 if (aclresult != ACLCHECK_OK)
9608                                         aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
9609                                                                    get_namespace_name(namespaceOid));
9610                         }
9611                 }
9612
9613                 memset(repl_null, false, sizeof(repl_null));
9614                 memset(repl_repl, false, sizeof(repl_repl));
9615
9616                 repl_repl[Anum_pg_class_relowner - 1] = true;
9617                 repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId);
9618
9619                 /*
9620                  * Determine the modified ACL for the new owner.  This is only
9621                  * necessary when the ACL is non-null.
9622                  */
9623                 aclDatum = SysCacheGetAttr(RELOID, tuple,
9624                                                                    Anum_pg_class_relacl,
9625                                                                    &isNull);
9626                 if (!isNull)
9627                 {
9628                         newAcl = aclnewowner(DatumGetAclP(aclDatum),
9629                                                                  tuple_class->relowner, newOwnerId);
9630                         repl_repl[Anum_pg_class_relacl - 1] = true;
9631                         repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl);
9632                 }
9633
9634                 newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl);
9635
9636                 CatalogTupleUpdate(class_rel, &newtuple->t_self, newtuple);
9637
9638                 heap_freetuple(newtuple);
9639
9640                 /*
9641                  * We must similarly update any per-column ACLs to reflect the new
9642                  * owner; for neatness reasons that's split out as a subroutine.
9643                  */
9644                 change_owner_fix_column_acls(relationOid,
9645                                                                          tuple_class->relowner,
9646                                                                          newOwnerId);
9647
9648                 /*
9649                  * Update owner dependency reference, if any.  A composite type has
9650                  * none, because it's tracked for the pg_type entry instead of here;
9651                  * indexes and TOAST tables don't have their own entries either.
9652                  */
9653                 if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE &&
9654                         tuple_class->relkind != RELKIND_INDEX &&
9655                         tuple_class->relkind != RELKIND_TOASTVALUE)
9656                         changeDependencyOnOwner(RelationRelationId, relationOid,
9657                                                                         newOwnerId);
9658
9659                 /*
9660                  * Also change the ownership of the table's row type, if it has one
9661                  */
9662                 if (tuple_class->relkind != RELKIND_INDEX)
9663                         AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId);
9664
9665                 /*
9666                  * If we are operating on a table or materialized view, also change
9667                  * the ownership of any indexes and sequences that belong to the
9668                  * relation, as well as its toast table (if it has one).
9669                  */
9670                 if (tuple_class->relkind == RELKIND_RELATION ||
9671                         tuple_class->relkind == RELKIND_MATVIEW ||
9672                         tuple_class->relkind == RELKIND_TOASTVALUE)
9673                 {
9674                         List       *index_oid_list;
9675                         ListCell   *i;
9676
9677                         /* Find all the indexes belonging to this relation */
9678                         index_oid_list = RelationGetIndexList(target_rel);
9679
9680                         /* For each index, recursively change its ownership */
9681                         foreach(i, index_oid_list)
9682                                 ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
9683
9684                         list_free(index_oid_list);
9685                 }
9686
9687                 if (tuple_class->relkind == RELKIND_RELATION ||
9688                         tuple_class->relkind == RELKIND_MATVIEW)
9689                 {
9690                         /* If it has a toast table, recurse to change its ownership */
9691                         if (tuple_class->reltoastrelid != InvalidOid)
9692                                 ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerId,
9693                                                                   true, lockmode);
9694
9695                         /* If it has dependent sequences, recurse to change them too */
9696                         change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
9697                 }
9698         }
9699
9700         InvokeObjectPostAlterHook(RelationRelationId, relationOid, 0);
9701
9702         ReleaseSysCache(tuple);
9703         heap_close(class_rel, RowExclusiveLock);
9704         relation_close(target_rel, NoLock);
9705 }
9706
9707 /*
9708  * change_owner_fix_column_acls
9709  *
9710  * Helper function for ATExecChangeOwner.  Scan the columns of the table
9711  * and fix any non-null column ACLs to reflect the new owner.
9712  */
9713 static void
9714 change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId)
9715 {
9716         Relation        attRelation;
9717         SysScanDesc scan;
9718         ScanKeyData key[1];
9719         HeapTuple       attributeTuple;
9720
9721         attRelation = heap_open(AttributeRelationId, RowExclusiveLock);
9722         ScanKeyInit(&key[0],
9723                                 Anum_pg_attribute_attrelid,
9724                                 BTEqualStrategyNumber, F_OIDEQ,
9725                                 ObjectIdGetDatum(relationOid));
9726         scan = systable_beginscan(attRelation, AttributeRelidNumIndexId,
9727                                                           true, NULL, 1, key);
9728         while (HeapTupleIsValid(attributeTuple = systable_getnext(scan)))
9729         {
9730                 Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple);
9731                 Datum           repl_val[Natts_pg_attribute];
9732                 bool            repl_null[Natts_pg_attribute];
9733                 bool            repl_repl[Natts_pg_attribute];
9734                 Acl                *newAcl;
9735                 Datum           aclDatum;
9736                 bool            isNull;
9737                 HeapTuple       newtuple;
9738
9739                 /* Ignore dropped columns */
9740                 if (att->attisdropped)
9741                         continue;
9742
9743                 aclDatum = heap_getattr(attributeTuple,
9744                                                                 Anum_pg_attribute_attacl,
9745                                                                 RelationGetDescr(attRelation),
9746                                                                 &isNull);
9747                 /* Null ACLs do not require changes */
9748                 if (isNull)
9749                         continue;
9750
9751                 memset(repl_null, false, sizeof(repl_null));
9752                 memset(repl_repl, false, sizeof(repl_repl));
9753
9754                 newAcl = aclnewowner(DatumGetAclP(aclDatum),
9755                                                          oldOwnerId, newOwnerId);
9756                 repl_repl[Anum_pg_attribute_attacl - 1] = true;
9757                 repl_val[Anum_pg_attribute_attacl - 1] = PointerGetDatum(newAcl);
9758
9759                 newtuple = heap_modify_tuple(attributeTuple,
9760                                                                          RelationGetDescr(attRelation),
9761                                                                          repl_val, repl_null, repl_repl);
9762
9763                 CatalogTupleUpdate(attRelation, &newtuple->t_self, newtuple);
9764
9765                 heap_freetuple(newtuple);
9766         }
9767         systable_endscan(scan);
9768         heap_close(attRelation, RowExclusiveLock);
9769 }
9770
9771 /*
9772  * change_owner_recurse_to_sequences
9773  *
9774  * Helper function for ATExecChangeOwner.  Examines pg_depend searching
9775  * for sequences that are dependent on serial columns, and changes their
9776  * ownership.
9777  */
9778 static void
9779 change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lockmode)
9780 {
9781         Relation        depRel;
9782         SysScanDesc scan;
9783         ScanKeyData key[2];
9784         HeapTuple       tup;
9785
9786         /*
9787          * SERIAL sequences are those having an auto dependency on one of the
9788          * table's columns (we don't care *which* column, exactly).
9789          */
9790         depRel = heap_open(DependRelationId, AccessShareLock);
9791
9792         ScanKeyInit(&key[0],
9793                                 Anum_pg_depend_refclassid,
9794                                 BTEqualStrategyNumber, F_OIDEQ,
9795                                 ObjectIdGetDatum(RelationRelationId));
9796         ScanKeyInit(&key[1],
9797                                 Anum_pg_depend_refobjid,
9798                                 BTEqualStrategyNumber, F_OIDEQ,
9799                                 ObjectIdGetDatum(relationOid));
9800         /* we leave refobjsubid unspecified */
9801
9802         scan = systable_beginscan(depRel, DependReferenceIndexId, true,
9803                                                           NULL, 2, key);
9804
9805         while (HeapTupleIsValid(tup = systable_getnext(scan)))
9806         {
9807                 Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
9808                 Relation        seqRel;
9809
9810                 /* skip dependencies other than auto dependencies on columns */
9811                 if (depForm->refobjsubid == 0 ||
9812                         depForm->classid != RelationRelationId ||
9813                         depForm->objsubid != 0 ||
9814                         depForm->deptype != DEPENDENCY_AUTO)
9815                         continue;
9816
9817                 /* Use relation_open just in case it's an index */
9818                 seqRel = relation_open(depForm->objid, lockmode);
9819
9820                 /* skip non-sequence relations */
9821                 if (RelationGetForm(seqRel)->relkind != RELKIND_SEQUENCE)
9822                 {
9823                         /* No need to keep the lock */
9824                         relation_close(seqRel, lockmode);
9825                         continue;
9826                 }
9827
9828                 /* We don't need to close the sequence while we alter it. */
9829                 ATExecChangeOwner(depForm->objid, newOwnerId, true, lockmode);
9830
9831                 /* Now we can close it.  Keep the lock till end of transaction. */
9832                 relation_close(seqRel, NoLock);
9833         }
9834
9835         systable_endscan(scan);
9836
9837         relation_close(depRel, AccessShareLock);
9838 }
9839
9840 /*
9841  * ALTER TABLE CLUSTER ON
9842  *
9843  * The only thing we have to do is to change the indisclustered bits.
9844  *
9845  * Return the address of the new clustering index.
9846  */
9847 static ObjectAddress
9848 ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode)
9849 {
9850         Oid                     indexOid;
9851         ObjectAddress address;
9852
9853         indexOid = get_relname_relid(indexName, rel->rd_rel->relnamespace);
9854
9855         if (!OidIsValid(indexOid))
9856                 ereport(ERROR,
9857                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
9858                                  errmsg("index \"%s\" for table \"%s\" does not exist",
9859                                                 indexName, RelationGetRelationName(rel))));
9860
9861         /* Check index is valid to cluster on */
9862         check_index_is_clusterable(rel, indexOid, false, lockmode);
9863
9864         /* And do the work */
9865         mark_index_clustered(rel, indexOid, false);
9866
9867         ObjectAddressSet(address,
9868                                          RelationRelationId, indexOid);
9869
9870         return address;
9871 }
9872
9873 /*
9874  * ALTER TABLE SET WITHOUT CLUSTER
9875  *
9876  * We have to find any indexes on the table that have indisclustered bit
9877  * set and turn it off.
9878  */
9879 static void
9880 ATExecDropCluster(Relation rel, LOCKMODE lockmode)
9881 {
9882         mark_index_clustered(rel, InvalidOid, false);
9883 }
9884
9885 /*
9886  * ALTER TABLE SET TABLESPACE
9887  */
9888 static void
9889 ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename, LOCKMODE lockmode)
9890 {
9891         Oid                     tablespaceId;
9892
9893         /* Check that the tablespace exists */
9894         tablespaceId = get_tablespace_oid(tablespacename, false);
9895
9896         /* Check permissions except when moving to database's default */
9897         if (OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
9898         {
9899                 AclResult       aclresult;
9900
9901                 aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(), ACL_CREATE);
9902                 if (aclresult != ACLCHECK_OK)
9903                         aclcheck_error(aclresult, ACL_KIND_TABLESPACE, tablespacename);
9904         }
9905
9906         /* Save info for Phase 3 to do the real work */
9907         if (OidIsValid(tab->newTableSpace))
9908                 ereport(ERROR,
9909                                 (errcode(ERRCODE_SYNTAX_ERROR),
9910                                  errmsg("cannot have multiple SET TABLESPACE subcommands")));
9911
9912         tab->newTableSpace = tablespaceId;
9913 }
9914
9915 /*
9916  * Set, reset, or replace reloptions.
9917  */
9918 static void
9919 ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
9920                                         LOCKMODE lockmode)
9921 {
9922         Oid                     relid;
9923         Relation        pgclass;
9924         HeapTuple       tuple;
9925         HeapTuple       newtuple;
9926         Datum           datum;
9927         bool            isnull;
9928         Datum           newOptions;
9929         Datum           repl_val[Natts_pg_class];
9930         bool            repl_null[Natts_pg_class];
9931         bool            repl_repl[Natts_pg_class];
9932         static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
9933
9934         if (defList == NIL && operation != AT_ReplaceRelOptions)
9935                 return;                                 /* nothing to do */
9936
9937         pgclass = heap_open(RelationRelationId, RowExclusiveLock);
9938
9939         /* Fetch heap tuple */
9940         relid = RelationGetRelid(rel);
9941         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
9942         if (!HeapTupleIsValid(tuple))
9943                 elog(ERROR, "cache lookup failed for relation %u", relid);
9944
9945         if (operation == AT_ReplaceRelOptions)
9946         {
9947                 /*
9948                  * If we're supposed to replace the reloptions list, we just pretend
9949                  * there were none before.
9950                  */
9951                 datum = (Datum) 0;
9952                 isnull = true;
9953         }
9954         else
9955         {
9956                 /* Get the old reloptions */
9957                 datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
9958                                                                 &isnull);
9959         }
9960
9961         /* Generate new proposed reloptions (text array) */
9962         newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
9963                                                                          defList, NULL, validnsps, false,
9964                                                                          operation == AT_ResetRelOptions);
9965
9966         /* Validate */
9967         switch (rel->rd_rel->relkind)
9968         {
9969                 case RELKIND_RELATION:
9970                 case RELKIND_TOASTVALUE:
9971                 case RELKIND_MATVIEW:
9972                 case RELKIND_PARTITIONED_TABLE:
9973                         (void) heap_reloptions(rel->rd_rel->relkind, newOptions, true);
9974                         break;
9975                 case RELKIND_VIEW:
9976                         (void) view_reloptions(newOptions, true);
9977                         break;
9978                 case RELKIND_INDEX:
9979                         (void) index_reloptions(rel->rd_amroutine->amoptions, newOptions, true);
9980                         break;
9981                 default:
9982                         ereport(ERROR,
9983                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9984                                          errmsg("\"%s\" is not a table, view, materialized view, index, or TOAST table",
9985                                                         RelationGetRelationName(rel))));
9986                         break;
9987         }
9988
9989         /* Special-case validation of view options */
9990         if (rel->rd_rel->relkind == RELKIND_VIEW)
9991         {
9992                 Query      *view_query = get_view_query(rel);
9993                 List       *view_options = untransformRelOptions(newOptions);
9994                 ListCell   *cell;
9995                 bool            check_option = false;
9996
9997                 foreach(cell, view_options)
9998                 {
9999                         DefElem    *defel = (DefElem *) lfirst(cell);
10000
10001                         if (pg_strcasecmp(defel->defname, "check_option") == 0)
10002                                 check_option = true;
10003                 }
10004
10005                 /*
10006                  * If the check option is specified, look to see if the view is
10007                  * actually auto-updatable or not.
10008                  */
10009                 if (check_option)
10010                 {
10011                         const char *view_updatable_error =
10012                         view_query_is_auto_updatable(view_query, true);
10013
10014                         if (view_updatable_error)
10015                                 ereport(ERROR,
10016                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
10017                                                  errmsg("WITH CHECK OPTION is supported only on automatically updatable views"),
10018                                                  errhint("%s", view_updatable_error)));
10019                 }
10020         }
10021
10022         /*
10023          * All we need do here is update the pg_class row; the new options will be
10024          * propagated into relcaches during post-commit cache inval.
10025          */
10026         memset(repl_val, 0, sizeof(repl_val));
10027         memset(repl_null, false, sizeof(repl_null));
10028         memset(repl_repl, false, sizeof(repl_repl));
10029
10030         if (newOptions != (Datum) 0)
10031                 repl_val[Anum_pg_class_reloptions - 1] = newOptions;
10032         else
10033                 repl_null[Anum_pg_class_reloptions - 1] = true;
10034
10035         repl_repl[Anum_pg_class_reloptions - 1] = true;
10036
10037         newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass),
10038                                                                  repl_val, repl_null, repl_repl);
10039
10040         CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple);
10041
10042         InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
10043
10044         heap_freetuple(newtuple);
10045
10046         ReleaseSysCache(tuple);
10047
10048         /* repeat the whole exercise for the toast table, if there's one */
10049         if (OidIsValid(rel->rd_rel->reltoastrelid))
10050         {
10051                 Relation        toastrel;
10052                 Oid                     toastid = rel->rd_rel->reltoastrelid;
10053
10054                 toastrel = heap_open(toastid, lockmode);
10055
10056                 /* Fetch heap tuple */
10057                 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(toastid));
10058                 if (!HeapTupleIsValid(tuple))
10059                         elog(ERROR, "cache lookup failed for relation %u", toastid);
10060
10061                 if (operation == AT_ReplaceRelOptions)
10062                 {
10063                         /*
10064                          * If we're supposed to replace the reloptions list, we just
10065                          * pretend there were none before.
10066                          */
10067                         datum = (Datum) 0;
10068                         isnull = true;
10069                 }
10070                 else
10071                 {
10072                         /* Get the old reloptions */
10073                         datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
10074                                                                         &isnull);
10075                 }
10076
10077                 newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
10078                                                                                  defList, "toast", validnsps, false,
10079                                                                                  operation == AT_ResetRelOptions);
10080
10081                 (void) heap_reloptions(RELKIND_TOASTVALUE, newOptions, true);
10082
10083                 memset(repl_val, 0, sizeof(repl_val));
10084                 memset(repl_null, false, sizeof(repl_null));
10085                 memset(repl_repl, false, sizeof(repl_repl));
10086
10087                 if (newOptions != (Datum) 0)
10088                         repl_val[Anum_pg_class_reloptions - 1] = newOptions;
10089                 else
10090                         repl_null[Anum_pg_class_reloptions - 1] = true;
10091
10092                 repl_repl[Anum_pg_class_reloptions - 1] = true;
10093
10094                 newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass),
10095                                                                          repl_val, repl_null, repl_repl);
10096
10097                 CatalogTupleUpdate(pgclass, &newtuple->t_self, newtuple);
10098
10099                 InvokeObjectPostAlterHookArg(RelationRelationId,
10100                                                                          RelationGetRelid(toastrel), 0,
10101                                                                          InvalidOid, true);
10102
10103                 heap_freetuple(newtuple);
10104
10105                 ReleaseSysCache(tuple);
10106
10107                 heap_close(toastrel, NoLock);
10108         }
10109
10110         heap_close(pgclass, RowExclusiveLock);
10111 }
10112
10113 /*
10114  * Execute ALTER TABLE SET TABLESPACE for cases where there is no tuple
10115  * rewriting to be done, so we just want to copy the data as fast as possible.
10116  */
10117 static void
10118 ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
10119 {
10120         Relation        rel;
10121         Oid                     oldTableSpace;
10122         Oid                     reltoastrelid;
10123         Oid                     newrelfilenode;
10124         RelFileNode newrnode;
10125         SMgrRelation dstrel;
10126         Relation        pg_class;
10127         HeapTuple       tuple;
10128         Form_pg_class rd_rel;
10129         ForkNumber      forkNum;
10130         List       *reltoastidxids = NIL;
10131         ListCell   *lc;
10132
10133         /*
10134          * Need lock here in case we are recursing to toast table or index
10135          */
10136         rel = relation_open(tableOid, lockmode);
10137
10138         /*
10139          * No work if no change in tablespace.
10140          */
10141         oldTableSpace = rel->rd_rel->reltablespace;
10142         if (newTableSpace == oldTableSpace ||
10143                 (newTableSpace == MyDatabaseTableSpace && oldTableSpace == 0))
10144         {
10145                 InvokeObjectPostAlterHook(RelationRelationId,
10146                                                                   RelationGetRelid(rel), 0);
10147
10148                 relation_close(rel, NoLock);
10149                 return;
10150         }
10151
10152         /*
10153          * We cannot support moving mapped relations into different tablespaces.
10154          * (In particular this eliminates all shared catalogs.)
10155          */
10156         if (RelationIsMapped(rel))
10157                 ereport(ERROR,
10158                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
10159                                  errmsg("cannot move system relation \"%s\"",
10160                                                 RelationGetRelationName(rel))));
10161
10162         /* Can't move a non-shared relation into pg_global */
10163         if (newTableSpace == GLOBALTABLESPACE_OID)
10164                 ereport(ERROR,
10165                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10166                                  errmsg("only shared relations can be placed in pg_global tablespace")));
10167
10168         /*
10169          * Don't allow moving temp tables of other backends ... their local buffer
10170          * manager is not going to cope.
10171          */
10172         if (RELATION_IS_OTHER_TEMP(rel))
10173                 ereport(ERROR,
10174                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
10175                                  errmsg("cannot move temporary tables of other sessions")));
10176
10177         reltoastrelid = rel->rd_rel->reltoastrelid;
10178         /* Fetch the list of indexes on toast relation if necessary */
10179         if (OidIsValid(reltoastrelid))
10180         {
10181                 Relation        toastRel = relation_open(reltoastrelid, lockmode);
10182
10183                 reltoastidxids = RelationGetIndexList(toastRel);
10184                 relation_close(toastRel, lockmode);
10185         }
10186
10187         /* Get a modifiable copy of the relation's pg_class row */
10188         pg_class = heap_open(RelationRelationId, RowExclusiveLock);
10189
10190         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(tableOid));
10191         if (!HeapTupleIsValid(tuple))
10192                 elog(ERROR, "cache lookup failed for relation %u", tableOid);
10193         rd_rel = (Form_pg_class) GETSTRUCT(tuple);
10194
10195         /*
10196          * Since we copy the file directly without looking at the shared buffers,
10197          * we'd better first flush out any pages of the source relation that are
10198          * in shared buffers.  We assume no new changes will be made while we are
10199          * holding exclusive lock on the rel.
10200          */
10201         FlushRelationBuffers(rel);
10202
10203         /*
10204          * Relfilenodes are not unique in databases across tablespaces, so we need
10205          * to allocate a new one in the new tablespace.
10206          */
10207         newrelfilenode = GetNewRelFileNode(newTableSpace, NULL,
10208                                                                            rel->rd_rel->relpersistence);
10209
10210         /* Open old and new relation */
10211         newrnode = rel->rd_node;
10212         newrnode.relNode = newrelfilenode;
10213         newrnode.spcNode = newTableSpace;
10214         dstrel = smgropen(newrnode, rel->rd_backend);
10215
10216         RelationOpenSmgr(rel);
10217
10218         /*
10219          * Create and copy all forks of the relation, and schedule unlinking of
10220          * old physical files.
10221          *
10222          * NOTE: any conflict in relfilenode value will be caught in
10223          * RelationCreateStorage().
10224          */
10225         RelationCreateStorage(newrnode, rel->rd_rel->relpersistence);
10226
10227         /* copy main fork */
10228         copy_relation_data(rel->rd_smgr, dstrel, MAIN_FORKNUM,
10229                                            rel->rd_rel->relpersistence);
10230
10231         /* copy those extra forks that exist */
10232         for (forkNum = MAIN_FORKNUM + 1; forkNum <= MAX_FORKNUM; forkNum++)
10233         {
10234                 if (smgrexists(rel->rd_smgr, forkNum))
10235                 {
10236                         smgrcreate(dstrel, forkNum, false);
10237
10238                         /*
10239                          * WAL log creation if the relation is persistent, or this is the
10240                          * init fork of an unlogged relation.
10241                          */
10242                         if (rel->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT ||
10243                                 (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED &&
10244                                  forkNum == INIT_FORKNUM))
10245                                 log_smgrcreate(&newrnode, forkNum);
10246                         copy_relation_data(rel->rd_smgr, dstrel, forkNum,
10247                                                            rel->rd_rel->relpersistence);
10248                 }
10249         }
10250
10251         /* drop old relation, and close new one */
10252         RelationDropStorage(rel);
10253         smgrclose(dstrel);
10254
10255         /* update the pg_class row */
10256         rd_rel->reltablespace = (newTableSpace == MyDatabaseTableSpace) ? InvalidOid : newTableSpace;
10257         rd_rel->relfilenode = newrelfilenode;
10258         CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
10259
10260         InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
10261
10262         heap_freetuple(tuple);
10263
10264         heap_close(pg_class, RowExclusiveLock);
10265
10266         relation_close(rel, NoLock);
10267
10268         /* Make sure the reltablespace change is visible */
10269         CommandCounterIncrement();
10270
10271         /* Move associated toast relation and/or indexes, too */
10272         if (OidIsValid(reltoastrelid))
10273                 ATExecSetTableSpace(reltoastrelid, newTableSpace, lockmode);
10274         foreach(lc, reltoastidxids)
10275                 ATExecSetTableSpace(lfirst_oid(lc), newTableSpace, lockmode);
10276
10277         /* Clean up */
10278         list_free(reltoastidxids);
10279 }
10280
10281 /*
10282  * Alter Table ALL ... SET TABLESPACE
10283  *
10284  * Allows a user to move all objects of some type in a given tablespace in the
10285  * current database to another tablespace.  Objects can be chosen based on the
10286  * owner of the object also, to allow users to move only their objects.
10287  * The user must have CREATE rights on the new tablespace, as usual.   The main
10288  * permissions handling is done by the lower-level table move function.
10289  *
10290  * All to-be-moved objects are locked first. If NOWAIT is specified and the
10291  * lock can't be acquired then we ereport(ERROR).
10292  */
10293 Oid
10294 AlterTableMoveAll(AlterTableMoveAllStmt *stmt)
10295 {
10296         List       *relations = NIL;
10297         ListCell   *l;
10298         ScanKeyData key[1];
10299         Relation        rel;
10300         HeapScanDesc scan;
10301         HeapTuple       tuple;
10302         Oid                     orig_tablespaceoid;
10303         Oid                     new_tablespaceoid;
10304         List       *role_oids = roleSpecsToIds(stmt->roles);
10305
10306         /* Ensure we were not asked to move something we can't */
10307         if (stmt->objtype != OBJECT_TABLE && stmt->objtype != OBJECT_INDEX &&
10308                 stmt->objtype != OBJECT_MATVIEW)
10309                 ereport(ERROR,
10310                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10311                                  errmsg("only tables, indexes, and materialized views exist in tablespaces")));
10312
10313         /* Get the orig and new tablespace OIDs */
10314         orig_tablespaceoid = get_tablespace_oid(stmt->orig_tablespacename, false);
10315         new_tablespaceoid = get_tablespace_oid(stmt->new_tablespacename, false);
10316
10317         /* Can't move shared relations in to or out of pg_global */
10318         /* This is also checked by ATExecSetTableSpace, but nice to stop earlier */
10319         if (orig_tablespaceoid == GLOBALTABLESPACE_OID ||
10320                 new_tablespaceoid == GLOBALTABLESPACE_OID)
10321                 ereport(ERROR,
10322                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
10323                                  errmsg("cannot move relations in to or out of pg_global tablespace")));
10324
10325         /*
10326          * Must have CREATE rights on the new tablespace, unless it is the
10327          * database default tablespace (which all users implicitly have CREATE
10328          * rights on).
10329          */
10330         if (OidIsValid(new_tablespaceoid) && new_tablespaceoid != MyDatabaseTableSpace)
10331         {
10332                 AclResult       aclresult;
10333
10334                 aclresult = pg_tablespace_aclcheck(new_tablespaceoid, GetUserId(),
10335                                                                                    ACL_CREATE);
10336                 if (aclresult != ACLCHECK_OK)
10337                         aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
10338                                                    get_tablespace_name(new_tablespaceoid));
10339         }
10340
10341         /*
10342          * Now that the checks are done, check if we should set either to
10343          * InvalidOid because it is our database's default tablespace.
10344          */
10345         if (orig_tablespaceoid == MyDatabaseTableSpace)
10346                 orig_tablespaceoid = InvalidOid;
10347
10348         if (new_tablespaceoid == MyDatabaseTableSpace)
10349                 new_tablespaceoid = InvalidOid;
10350
10351         /* no-op */
10352         if (orig_tablespaceoid == new_tablespaceoid)
10353                 return new_tablespaceoid;
10354
10355         /*
10356          * Walk the list of objects in the tablespace and move them. This will
10357          * only find objects in our database, of course.
10358          */
10359         ScanKeyInit(&key[0],
10360                                 Anum_pg_class_reltablespace,
10361                                 BTEqualStrategyNumber, F_OIDEQ,
10362                                 ObjectIdGetDatum(orig_tablespaceoid));
10363
10364         rel = heap_open(RelationRelationId, AccessShareLock);
10365         scan = heap_beginscan_catalog(rel, 1, key);
10366         while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
10367         {
10368                 Oid                     relOid = HeapTupleGetOid(tuple);
10369                 Form_pg_class relForm;
10370
10371                 relForm = (Form_pg_class) GETSTRUCT(tuple);
10372
10373                 /*
10374                  * Do not move objects in pg_catalog as part of this, if an admin
10375                  * really wishes to do so, they can issue the individual ALTER
10376                  * commands directly.
10377                  *
10378                  * Also, explicitly avoid any shared tables, temp tables, or TOAST
10379                  * (TOAST will be moved with the main table).
10380                  */
10381                 if (IsSystemNamespace(relForm->relnamespace) || relForm->relisshared ||
10382                         isAnyTempNamespace(relForm->relnamespace) ||
10383                         relForm->relnamespace == PG_TOAST_NAMESPACE)
10384                         continue;
10385
10386                 /* Only move the object type requested */
10387                 if ((stmt->objtype == OBJECT_TABLE &&
10388                          relForm->relkind != RELKIND_RELATION &&
10389                          relForm->relkind != RELKIND_PARTITIONED_TABLE) ||
10390                         (stmt->objtype == OBJECT_INDEX &&
10391                          relForm->relkind != RELKIND_INDEX) ||
10392                         (stmt->objtype == OBJECT_MATVIEW &&
10393                          relForm->relkind != RELKIND_MATVIEW))
10394                         continue;
10395
10396                 /* Check if we are only moving objects owned by certain roles */
10397                 if (role_oids != NIL && !list_member_oid(role_oids, relForm->relowner))
10398                         continue;
10399
10400                 /*
10401                  * Handle permissions-checking here since we are locking the tables
10402                  * and also to avoid doing a bunch of work only to fail part-way. Note
10403                  * that permissions will also be checked by AlterTableInternal().
10404                  *
10405                  * Caller must be considered an owner on the table to move it.
10406                  */
10407                 if (!pg_class_ownercheck(relOid, GetUserId()))
10408                         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
10409                                                    NameStr(relForm->relname));
10410
10411                 if (stmt->nowait &&
10412                         !ConditionalLockRelationOid(relOid, AccessExclusiveLock))
10413                         ereport(ERROR,
10414                                         (errcode(ERRCODE_OBJECT_IN_USE),
10415                                          errmsg("aborting because lock on relation \"%s.%s\" is not available",
10416                                                         get_namespace_name(relForm->relnamespace),
10417                                                         NameStr(relForm->relname))));
10418                 else
10419                         LockRelationOid(relOid, AccessExclusiveLock);
10420
10421                 /* Add to our list of objects to move */
10422                 relations = lappend_oid(relations, relOid);
10423         }
10424
10425         heap_endscan(scan);
10426         heap_close(rel, AccessShareLock);
10427
10428         if (relations == NIL)
10429                 ereport(NOTICE,
10430                                 (errcode(ERRCODE_NO_DATA_FOUND),
10431                                  errmsg("no matching relations in tablespace \"%s\" found",
10432                                         orig_tablespaceoid == InvalidOid ? "(database default)" :
10433                                                 get_tablespace_name(orig_tablespaceoid))));
10434
10435         /* Everything is locked, loop through and move all of the relations. */
10436         foreach(l, relations)
10437         {
10438                 List       *cmds = NIL;
10439                 AlterTableCmd *cmd = makeNode(AlterTableCmd);
10440
10441                 cmd->subtype = AT_SetTableSpace;
10442                 cmd->name = stmt->new_tablespacename;
10443
10444                 cmds = lappend(cmds, cmd);
10445
10446                 EventTriggerAlterTableStart((Node *) stmt);
10447                 /* OID is set by AlterTableInternal */
10448                 AlterTableInternal(lfirst_oid(l), cmds, false);
10449                 EventTriggerAlterTableEnd();
10450         }
10451
10452         return new_tablespaceoid;
10453 }
10454
10455 /*
10456  * Copy data, block by block
10457  */
10458 static void
10459 copy_relation_data(SMgrRelation src, SMgrRelation dst,
10460                                    ForkNumber forkNum, char relpersistence)
10461 {
10462         char       *buf;
10463         Page            page;
10464         bool            use_wal;
10465         bool            copying_initfork;
10466         BlockNumber nblocks;
10467         BlockNumber blkno;
10468
10469         /*
10470          * palloc the buffer so that it's MAXALIGN'd.  If it were just a local
10471          * char[] array, the compiler might align it on any byte boundary, which
10472          * can seriously hurt transfer speed to and from the kernel; not to
10473          * mention possibly making log_newpage's accesses to the page header fail.
10474          */
10475         buf = (char *) palloc(BLCKSZ);
10476         page = (Page) buf;
10477
10478         /*
10479          * The init fork for an unlogged relation in many respects has to be
10480          * treated the same as normal relation, changes need to be WAL logged and
10481          * it needs to be synced to disk.
10482          */
10483         copying_initfork = relpersistence == RELPERSISTENCE_UNLOGGED &&
10484                 forkNum == INIT_FORKNUM;
10485
10486         /*
10487          * We need to log the copied data in WAL iff WAL archiving/streaming is
10488          * enabled AND it's a permanent relation.
10489          */
10490         use_wal = XLogIsNeeded() &&
10491                 (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork);
10492
10493         nblocks = smgrnblocks(src, forkNum);
10494
10495         for (blkno = 0; blkno < nblocks; blkno++)
10496         {
10497                 /* If we got a cancel signal during the copy of the data, quit */
10498                 CHECK_FOR_INTERRUPTS();
10499
10500                 smgrread(src, forkNum, blkno, buf);
10501
10502                 if (!PageIsVerified(page, blkno))
10503                         ereport(ERROR,
10504                                         (errcode(ERRCODE_DATA_CORRUPTED),
10505                                          errmsg("invalid page in block %u of relation %s",
10506                                                         blkno,
10507                                                         relpathbackend(src->smgr_rnode.node,
10508                                                                                    src->smgr_rnode.backend,
10509                                                                                    forkNum))));
10510
10511                 /*
10512                  * WAL-log the copied page. Unfortunately we don't know what kind of a
10513                  * page this is, so we have to log the full page including any unused
10514                  * space.
10515                  */
10516                 if (use_wal)
10517                         log_newpage(&dst->smgr_rnode.node, forkNum, blkno, page, false);
10518
10519                 PageSetChecksumInplace(page, blkno);
10520
10521                 /*
10522                  * Now write the page.  We say isTemp = true even if it's not a temp
10523                  * rel, because there's no need for smgr to schedule an fsync for this
10524                  * write; we'll do it ourselves below.
10525                  */
10526                 smgrextend(dst, forkNum, blkno, buf, true);
10527         }
10528
10529         pfree(buf);
10530
10531         /*
10532          * If the rel is WAL-logged, must fsync before commit.  We use heap_sync
10533          * to ensure that the toast table gets fsync'd too.  (For a temp or
10534          * unlogged rel we don't care since the data will be gone after a crash
10535          * anyway.)
10536          *
10537          * It's obvious that we must do this when not WAL-logging the copy. It's
10538          * less obvious that we have to do it even if we did WAL-log the copied
10539          * pages. The reason is that since we're copying outside shared buffers, a
10540          * CHECKPOINT occurring during the copy has no way to flush the previously
10541          * written data to disk (indeed it won't know the new rel even exists).  A
10542          * crash later on would replay WAL from the checkpoint, therefore it
10543          * wouldn't replay our earlier WAL entries. If we do not fsync those pages
10544          * here, they might still not be on disk when the crash occurs.
10545          */
10546         if (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork)
10547                 smgrimmedsync(dst, forkNum);
10548 }
10549
10550 /*
10551  * ALTER TABLE ENABLE/DISABLE TRIGGER
10552  *
10553  * We just pass this off to trigger.c.
10554  */
10555 static void
10556 ATExecEnableDisableTrigger(Relation rel, char *trigname,
10557                                                 char fires_when, bool skip_system, LOCKMODE lockmode)
10558 {
10559         EnableDisableTrigger(rel, trigname, fires_when, skip_system);
10560 }
10561
10562 /*
10563  * ALTER TABLE ENABLE/DISABLE RULE
10564  *
10565  * We just pass this off to rewriteDefine.c.
10566  */
10567 static void
10568 ATExecEnableDisableRule(Relation rel, char *rulename,
10569                                                 char fires_when, LOCKMODE lockmode)
10570 {
10571         EnableDisableRule(rel, rulename, fires_when);
10572 }
10573
10574 /*
10575  * ALTER TABLE INHERIT
10576  *
10577  * Add a parent to the child's parents. This verifies that all the columns and
10578  * check constraints of the parent appear in the child and that they have the
10579  * same data types and expressions.
10580  */
10581 static void
10582 ATPrepAddInherit(Relation child_rel)
10583 {
10584         if (child_rel->rd_rel->reloftype)
10585                 ereport(ERROR,
10586                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10587                                  errmsg("cannot change inheritance of typed table")));
10588
10589         if (child_rel->rd_rel->relispartition)
10590                 ereport(ERROR,
10591                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10592                                  errmsg("cannot change inheritance of a partition")));
10593
10594         if (child_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
10595                 ereport(ERROR,
10596                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10597                                  errmsg("cannot change inheritance of partitioned table")));
10598 }
10599
10600 /*
10601  * Return the address of the new parent relation.
10602  */
10603 static ObjectAddress
10604 ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
10605 {
10606         Relation        parent_rel;
10607         List       *children;
10608         ObjectAddress address;
10609
10610         /*
10611          * A self-exclusive lock is needed here.  See the similar case in
10612          * MergeAttributes() for a full explanation.
10613          */
10614         parent_rel = heap_openrv(parent, ShareUpdateExclusiveLock);
10615
10616         /*
10617          * Must be owner of both parent and child -- child was checked by
10618          * ATSimplePermissions call in ATPrepCmd
10619          */
10620         ATSimplePermissions(parent_rel, ATT_TABLE | ATT_FOREIGN_TABLE);
10621
10622         /* Permanent rels cannot inherit from temporary ones */
10623         if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
10624                 child_rel->rd_rel->relpersistence != RELPERSISTENCE_TEMP)
10625                 ereport(ERROR,
10626                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10627                                  errmsg("cannot inherit from temporary relation \"%s\"",
10628                                                 RelationGetRelationName(parent_rel))));
10629
10630         /* If parent rel is temp, it must belong to this session */
10631         if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
10632                 !parent_rel->rd_islocaltemp)
10633                 ereport(ERROR,
10634                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10635                 errmsg("cannot inherit from temporary relation of another session")));
10636
10637         /* Ditto for the child */
10638         if (child_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
10639                 !child_rel->rd_islocaltemp)
10640                 ereport(ERROR,
10641                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10642                  errmsg("cannot inherit to temporary relation of another session")));
10643
10644         /* Prevent partitioned tables from becoming inheritance parents */
10645         if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
10646                 ereport(ERROR,
10647                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10648                                  errmsg("cannot inherit from partitioned table \"%s\"",
10649                                                 parent->relname)));
10650
10651         /* Likewise for partitions */
10652         if (parent_rel->rd_rel->relispartition)
10653                 ereport(ERROR,
10654                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10655                                  errmsg("cannot inherit from a partition")));
10656
10657         /*
10658          * Prevent circularity by seeing if proposed parent inherits from child.
10659          * (In particular, this disallows making a rel inherit from itself.)
10660          *
10661          * This is not completely bulletproof because of race conditions: in
10662          * multi-level inheritance trees, someone else could concurrently be
10663          * making another inheritance link that closes the loop but does not join
10664          * either of the rels we have locked.  Preventing that seems to require
10665          * exclusive locks on the entire inheritance tree, which is a cure worse
10666          * than the disease.  find_all_inheritors() will cope with circularity
10667          * anyway, so don't sweat it too much.
10668          *
10669          * We use weakest lock we can on child's children, namely AccessShareLock.
10670          */
10671         children = find_all_inheritors(RelationGetRelid(child_rel),
10672                                                                    AccessShareLock, NULL);
10673
10674         if (list_member_oid(children, RelationGetRelid(parent_rel)))
10675                 ereport(ERROR,
10676                                 (errcode(ERRCODE_DUPLICATE_TABLE),
10677                                  errmsg("circular inheritance not allowed"),
10678                                  errdetail("\"%s\" is already a child of \"%s\".",
10679                                                    parent->relname,
10680                                                    RelationGetRelationName(child_rel))));
10681
10682         /* If parent has OIDs then child must have OIDs */
10683         if (parent_rel->rd_rel->relhasoids && !child_rel->rd_rel->relhasoids)
10684                 ereport(ERROR,
10685                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10686                                  errmsg("table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs",
10687                                                 RelationGetRelationName(child_rel),
10688                                                 RelationGetRelationName(parent_rel))));
10689
10690         /* OK to create inheritance */
10691         CreateInheritance(child_rel, parent_rel);
10692
10693         ObjectAddressSet(address, RelationRelationId,
10694                                          RelationGetRelid(parent_rel));
10695
10696         /* keep our lock on the parent relation until commit */
10697         heap_close(parent_rel, NoLock);
10698
10699         return address;
10700 }
10701
10702 /*
10703  * CreateInheritance
10704  *              Catalog manipulation portion of creating inheritance between a child
10705  *              table and a parent table.
10706  *
10707  * Common to ATExecAddInherit() and ATExecAttachPartition().
10708  */
10709 static void
10710 CreateInheritance(Relation child_rel, Relation parent_rel)
10711 {
10712         Relation        catalogRelation;
10713         SysScanDesc scan;
10714         ScanKeyData key;
10715         HeapTuple       inheritsTuple;
10716         int32           inhseqno;
10717
10718         /* Note: get RowExclusiveLock because we will write pg_inherits below. */
10719         catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
10720
10721         /*
10722          * Check for duplicates in the list of parents, and determine the highest
10723          * inhseqno already present; we'll use the next one for the new parent.
10724          * Also, if proposed child is a partition, it cannot already be
10725          * inheriting.
10726          *
10727          * Note: we do not reject the case where the child already inherits from
10728          * the parent indirectly; CREATE TABLE doesn't reject comparable cases.
10729          */
10730         ScanKeyInit(&key,
10731                                 Anum_pg_inherits_inhrelid,
10732                                 BTEqualStrategyNumber, F_OIDEQ,
10733                                 ObjectIdGetDatum(RelationGetRelid(child_rel)));
10734         scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
10735                                                           true, NULL, 1, &key);
10736
10737         /* inhseqno sequences start at 1 */
10738         inhseqno = 0;
10739         while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
10740         {
10741                 Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inheritsTuple);
10742
10743                 if (inh->inhparent == RelationGetRelid(parent_rel))
10744                         ereport(ERROR,
10745                                         (errcode(ERRCODE_DUPLICATE_TABLE),
10746                          errmsg("relation \"%s\" would be inherited from more than once",
10747                                         RelationGetRelationName(parent_rel))));
10748
10749                 if (inh->inhseqno > inhseqno)
10750                         inhseqno = inh->inhseqno;
10751         }
10752         systable_endscan(scan);
10753
10754         /* Match up the columns and bump attinhcount as needed */
10755         MergeAttributesIntoExisting(child_rel, parent_rel);
10756
10757         /* Match up the constraints and bump coninhcount as needed */
10758         MergeConstraintsIntoExisting(child_rel, parent_rel);
10759
10760         /*
10761          * OK, it looks valid.  Make the catalog entries that show inheritance.
10762          */
10763         StoreCatalogInheritance1(RelationGetRelid(child_rel),
10764                                                          RelationGetRelid(parent_rel),
10765                                                          inhseqno + 1,
10766                                                          catalogRelation,
10767                                                          parent_rel->rd_rel->relkind ==
10768                                                                                         RELKIND_PARTITIONED_TABLE);
10769
10770         /* Now we're done with pg_inherits */
10771         heap_close(catalogRelation, RowExclusiveLock);
10772 }
10773
10774 /*
10775  * Obtain the source-text form of the constraint expression for a check
10776  * constraint, given its pg_constraint tuple
10777  */
10778 static char *
10779 decompile_conbin(HeapTuple contup, TupleDesc tupdesc)
10780 {
10781         Form_pg_constraint con;
10782         bool            isnull;
10783         Datum           attr;
10784         Datum           expr;
10785
10786         con = (Form_pg_constraint) GETSTRUCT(contup);
10787         attr = heap_getattr(contup, Anum_pg_constraint_conbin, tupdesc, &isnull);
10788         if (isnull)
10789                 elog(ERROR, "null conbin for constraint %u", HeapTupleGetOid(contup));
10790
10791         expr = DirectFunctionCall2(pg_get_expr, attr,
10792                                                            ObjectIdGetDatum(con->conrelid));
10793         return TextDatumGetCString(expr);
10794 }
10795
10796 /*
10797  * Determine whether two check constraints are functionally equivalent
10798  *
10799  * The test we apply is to see whether they reverse-compile to the same
10800  * source string.  This insulates us from issues like whether attributes
10801  * have the same physical column numbers in parent and child relations.
10802  */
10803 static bool
10804 constraints_equivalent(HeapTuple a, HeapTuple b, TupleDesc tupleDesc)
10805 {
10806         Form_pg_constraint acon = (Form_pg_constraint) GETSTRUCT(a);
10807         Form_pg_constraint bcon = (Form_pg_constraint) GETSTRUCT(b);
10808
10809         if (acon->condeferrable != bcon->condeferrable ||
10810                 acon->condeferred != bcon->condeferred ||
10811                 strcmp(decompile_conbin(a, tupleDesc),
10812                            decompile_conbin(b, tupleDesc)) != 0)
10813                 return false;
10814         else
10815                 return true;
10816 }
10817
10818 /*
10819  * Check columns in child table match up with columns in parent, and increment
10820  * their attinhcount.
10821  *
10822  * Called by CreateInheritance
10823  *
10824  * Currently all parent columns must be found in child. Missing columns are an
10825  * error.  One day we might consider creating new columns like CREATE TABLE
10826  * does.  However, that is widely unpopular --- in the common use case of
10827  * partitioned tables it's a foot-gun.
10828  *
10829  * The data type must match exactly. If the parent column is NOT NULL then
10830  * the child must be as well. Defaults are not compared, however.
10831  */
10832 static void
10833 MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
10834 {
10835         Relation        attrrel;
10836         AttrNumber      parent_attno;
10837         int                     parent_natts;
10838         TupleDesc       tupleDesc;
10839         HeapTuple       tuple;
10840         bool            child_is_partition = false;
10841
10842         attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
10843
10844         tupleDesc = RelationGetDescr(parent_rel);
10845         parent_natts = tupleDesc->natts;
10846
10847         /* If parent_rel is a partitioned table, child_rel must be a partition */
10848         if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
10849                 child_is_partition = true;
10850
10851         for (parent_attno = 1; parent_attno <= parent_natts; parent_attno++)
10852         {
10853                 Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
10854                 char       *attributeName = NameStr(attribute->attname);
10855
10856                 /* Ignore dropped columns in the parent. */
10857                 if (attribute->attisdropped)
10858                         continue;
10859
10860                 /* Find same column in child (matching on column name). */
10861                 tuple = SearchSysCacheCopyAttName(RelationGetRelid(child_rel),
10862                                                                                   attributeName);
10863                 if (HeapTupleIsValid(tuple))
10864                 {
10865                         /* Check they are same type, typmod, and collation */
10866                         Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
10867
10868                         if (attribute->atttypid != childatt->atttypid ||
10869                                 attribute->atttypmod != childatt->atttypmod)
10870                                 ereport(ERROR,
10871                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
10872                                                  errmsg("child table \"%s\" has different type for column \"%s\"",
10873                                                                 RelationGetRelationName(child_rel),
10874                                                                 attributeName)));
10875
10876                         if (attribute->attcollation != childatt->attcollation)
10877                                 ereport(ERROR,
10878                                                 (errcode(ERRCODE_COLLATION_MISMATCH),
10879                                                  errmsg("child table \"%s\" has different collation for column \"%s\"",
10880                                                                 RelationGetRelationName(child_rel),
10881                                                                 attributeName)));
10882
10883                         /*
10884                          * Check child doesn't discard NOT NULL property.  (Other
10885                          * constraints are checked elsewhere.)
10886                          */
10887                         if (attribute->attnotnull && !childatt->attnotnull)
10888                                 ereport(ERROR,
10889                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
10890                                 errmsg("column \"%s\" in child table must be marked NOT NULL",
10891                                            attributeName)));
10892
10893                         /*
10894                          * OK, bump the child column's inheritance count.  (If we fail
10895                          * later on, this change will just roll back.)
10896                          */
10897                         childatt->attinhcount++;
10898
10899                         /*
10900                          * In case of partitions, we must enforce that value of attislocal
10901                          * is same in all partitions. (Note: there are only inherited
10902                          * attributes in partitions)
10903                          */
10904                         if (child_is_partition)
10905                         {
10906                                 Assert(childatt->attinhcount == 1);
10907                                 childatt->attislocal = false;
10908                         }
10909
10910                         CatalogTupleUpdate(attrrel, &tuple->t_self, tuple);
10911                         heap_freetuple(tuple);
10912                 }
10913                 else
10914                 {
10915                         ereport(ERROR,
10916                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
10917                                          errmsg("child table is missing column \"%s\"",
10918                                                         attributeName)));
10919                 }
10920         }
10921
10922         /*
10923          * If the parent has an OID column, so must the child, and we'd better
10924          * update the child's attinhcount and attislocal the same as for normal
10925          * columns.  We needn't check data type or not-nullness though.
10926          */
10927         if (tupleDesc->tdhasoid)
10928         {
10929                 /*
10930                  * Here we match by column number not name; the match *must* be the
10931                  * system column, not some random column named "oid".
10932                  */
10933                 tuple = SearchSysCacheCopy2(ATTNUM,
10934                                                            ObjectIdGetDatum(RelationGetRelid(child_rel)),
10935                                                                         Int16GetDatum(ObjectIdAttributeNumber));
10936                 if (HeapTupleIsValid(tuple))
10937                 {
10938                         Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
10939
10940                         /* See comments above; these changes should be the same */
10941                         childatt->attinhcount++;
10942
10943                         if (child_is_partition)
10944                         {
10945                                 Assert(childatt->attinhcount == 1);
10946                                 childatt->attislocal = false;
10947                         }
10948
10949                         CatalogTupleUpdate(attrrel, &tuple->t_self, tuple);
10950                         heap_freetuple(tuple);
10951                 }
10952                 else
10953                 {
10954                         ereport(ERROR,
10955                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
10956                                          errmsg("child table is missing column \"%s\"",
10957                                                         "oid")));
10958                 }
10959         }
10960
10961         heap_close(attrrel, RowExclusiveLock);
10962 }
10963
10964 /*
10965  * Check constraints in child table match up with constraints in parent,
10966  * and increment their coninhcount.
10967  *
10968  * Constraints that are marked ONLY in the parent are ignored.
10969  *
10970  * Called by CreateInheritance
10971  *
10972  * Currently all constraints in parent must be present in the child. One day we
10973  * may consider adding new constraints like CREATE TABLE does.
10974  *
10975  * XXX This is O(N^2) which may be an issue with tables with hundreds of
10976  * constraints. As long as tables have more like 10 constraints it shouldn't be
10977  * a problem though. Even 100 constraints ought not be the end of the world.
10978  *
10979  * XXX See MergeWithExistingConstraint too if you change this code.
10980  */
10981 static void
10982 MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
10983 {
10984         Relation        catalog_relation;
10985         TupleDesc       tuple_desc;
10986         SysScanDesc parent_scan;
10987         ScanKeyData parent_key;
10988         HeapTuple       parent_tuple;
10989         bool            child_is_partition = false;
10990
10991         catalog_relation = heap_open(ConstraintRelationId, RowExclusiveLock);
10992         tuple_desc = RelationGetDescr(catalog_relation);
10993
10994         /* If parent_rel is a partitioned table, child_rel must be a partition */
10995         if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
10996                 child_is_partition = true;
10997
10998         /* Outer loop scans through the parent's constraint definitions */
10999         ScanKeyInit(&parent_key,
11000                                 Anum_pg_constraint_conrelid,
11001                                 BTEqualStrategyNumber, F_OIDEQ,
11002                                 ObjectIdGetDatum(RelationGetRelid(parent_rel)));
11003         parent_scan = systable_beginscan(catalog_relation, ConstraintRelidIndexId,
11004                                                                          true, NULL, 1, &parent_key);
11005
11006         while (HeapTupleIsValid(parent_tuple = systable_getnext(parent_scan)))
11007         {
11008                 Form_pg_constraint parent_con = (Form_pg_constraint) GETSTRUCT(parent_tuple);
11009                 SysScanDesc child_scan;
11010                 ScanKeyData child_key;
11011                 HeapTuple       child_tuple;
11012                 bool            found = false;
11013
11014                 if (parent_con->contype != CONSTRAINT_CHECK)
11015                         continue;
11016
11017                 /* if the parent's constraint is marked NO INHERIT, it's not inherited */
11018                 if (parent_con->connoinherit)
11019                         continue;
11020
11021                 /* Search for a child constraint matching this one */
11022                 ScanKeyInit(&child_key,
11023                                         Anum_pg_constraint_conrelid,
11024                                         BTEqualStrategyNumber, F_OIDEQ,
11025                                         ObjectIdGetDatum(RelationGetRelid(child_rel)));
11026                 child_scan = systable_beginscan(catalog_relation, ConstraintRelidIndexId,
11027                                                                                 true, NULL, 1, &child_key);
11028
11029                 while (HeapTupleIsValid(child_tuple = systable_getnext(child_scan)))
11030                 {
11031                         Form_pg_constraint child_con = (Form_pg_constraint) GETSTRUCT(child_tuple);
11032                         HeapTuple       child_copy;
11033
11034                         if (child_con->contype != CONSTRAINT_CHECK)
11035                                 continue;
11036
11037                         if (strcmp(NameStr(parent_con->conname),
11038                                            NameStr(child_con->conname)) != 0)
11039                                 continue;
11040
11041                         if (!constraints_equivalent(parent_tuple, child_tuple, tuple_desc))
11042                                 ereport(ERROR,
11043                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
11044                                                  errmsg("child table \"%s\" has different definition for check constraint \"%s\"",
11045                                                                 RelationGetRelationName(child_rel),
11046                                                                 NameStr(parent_con->conname))));
11047
11048                         /* If the child constraint is "no inherit" then cannot merge */
11049                         if (child_con->connoinherit)
11050                                 ereport(ERROR,
11051                                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
11052                                                  errmsg("constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"",
11053                                                                 NameStr(child_con->conname),
11054                                                                 RelationGetRelationName(child_rel))));
11055
11056                         /*
11057                          * If the child constraint is "not valid" then cannot merge with a
11058                          * valid parent constraint
11059                          */
11060                         if (parent_con->convalidated && !child_con->convalidated)
11061                                 ereport(ERROR,
11062                                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
11063                                                  errmsg("constraint \"%s\" conflicts with NOT VALID constraint on child table \"%s\"",
11064                                                                 NameStr(child_con->conname),
11065                                                                 RelationGetRelationName(child_rel))));
11066
11067                         /*
11068                          * OK, bump the child constraint's inheritance count.  (If we fail
11069                          * later on, this change will just roll back.)
11070                          */
11071                         child_copy = heap_copytuple(child_tuple);
11072                         child_con = (Form_pg_constraint) GETSTRUCT(child_copy);
11073                         child_con->coninhcount++;
11074
11075                         /*
11076                          * In case of partitions, an inherited constraint must be
11077                          * inherited only once since it cannot have multiple parents and
11078                          * it is never considered local.
11079                          */
11080                         if (child_is_partition)
11081                         {
11082                                 Assert(child_con->coninhcount == 1);
11083                                 child_con->conislocal = false;
11084                         }
11085
11086                         CatalogTupleUpdate(catalog_relation, &child_copy->t_self, child_copy);
11087                         heap_freetuple(child_copy);
11088
11089                         found = true;
11090                         break;
11091                 }
11092
11093                 systable_endscan(child_scan);
11094
11095                 if (!found)
11096                         ereport(ERROR,
11097                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
11098                                          errmsg("child table is missing constraint \"%s\"",
11099                                                         NameStr(parent_con->conname))));
11100         }
11101
11102         systable_endscan(parent_scan);
11103         heap_close(catalog_relation, RowExclusiveLock);
11104 }
11105
11106 /*
11107  * ALTER TABLE NO INHERIT
11108  *
11109  * Return value is the address of the relation that is no longer parent.
11110  */
11111 static ObjectAddress
11112 ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
11113 {
11114         ObjectAddress address;
11115         Relation        parent_rel;
11116
11117         if (rel->rd_rel->relispartition)
11118                 ereport(ERROR,
11119                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11120                                  errmsg("cannot change inheritance of a partition")));
11121
11122         /*
11123          * AccessShareLock on the parent is probably enough, seeing that DROP
11124          * TABLE doesn't lock parent tables at all.  We need some lock since we'll
11125          * be inspecting the parent's schema.
11126          */
11127         parent_rel = heap_openrv(parent, AccessShareLock);
11128
11129         /*
11130          * We don't bother to check ownership of the parent table --- ownership of
11131          * the child is presumed enough rights.
11132          */
11133
11134         /* Off to RemoveInheritance() where most of the work happens */
11135         RemoveInheritance(rel, parent_rel);
11136
11137         /* keep our lock on the parent relation until commit */
11138         heap_close(parent_rel, NoLock);
11139
11140         ObjectAddressSet(address, RelationRelationId,
11141                                          RelationGetRelid(parent_rel));
11142
11143         return address;
11144 }
11145
11146 /*
11147  * RemoveInheritance
11148  *
11149  * Drop a parent from the child's parents. This just adjusts the attinhcount
11150  * and attislocal of the columns and removes the pg_inherit and pg_depend
11151  * entries.
11152  *
11153  * If attinhcount goes to 0 then attislocal gets set to true. If it goes back
11154  * up attislocal stays true, which means if a child is ever removed from a
11155  * parent then its columns will never be automatically dropped which may
11156  * surprise. But at least we'll never surprise by dropping columns someone
11157  * isn't expecting to be dropped which would actually mean data loss.
11158  *
11159  * coninhcount and conislocal for inherited constraints are adjusted in
11160  * exactly the same way.
11161  *
11162  * Common to ATExecDropInherit() and ATExecDetachPartition().
11163  */
11164 static void
11165 RemoveInheritance(Relation child_rel, Relation parent_rel)
11166 {
11167         Relation        catalogRelation;
11168         SysScanDesc scan;
11169         ScanKeyData key[3];
11170         HeapTuple       inheritsTuple,
11171                                 attributeTuple,
11172                                 constraintTuple;
11173         List       *connames;
11174         bool            found = false;
11175         bool            child_is_partition = false;
11176
11177         /* If parent_rel is a partitioned table, child_rel must be a partition */
11178         if (parent_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
11179                 child_is_partition = true;
11180
11181         /*
11182          * Find and destroy the pg_inherits entry linking the two, or error out if
11183          * there is none.
11184          */
11185         catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
11186         ScanKeyInit(&key[0],
11187                                 Anum_pg_inherits_inhrelid,
11188                                 BTEqualStrategyNumber, F_OIDEQ,
11189                                 ObjectIdGetDatum(RelationGetRelid(child_rel)));
11190         scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
11191                                                           true, NULL, 1, key);
11192
11193         while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
11194         {
11195                 Oid                     inhparent;
11196
11197                 inhparent = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhparent;
11198                 if (inhparent == RelationGetRelid(parent_rel))
11199                 {
11200                         CatalogTupleDelete(catalogRelation, &inheritsTuple->t_self);
11201                         found = true;
11202                         break;
11203                 }
11204         }
11205
11206         systable_endscan(scan);
11207         heap_close(catalogRelation, RowExclusiveLock);
11208
11209         if (!found)
11210         {
11211                 if (child_is_partition)
11212                         ereport(ERROR,
11213                                         (errcode(ERRCODE_UNDEFINED_TABLE),
11214                           errmsg("relation \"%s\" is not a partition of relation \"%s\"",
11215                                          RelationGetRelationName(child_rel),
11216                                          RelationGetRelationName(parent_rel))));
11217                 else
11218                         ereport(ERROR,
11219                                         (errcode(ERRCODE_UNDEFINED_TABLE),
11220                                  errmsg("relation \"%s\" is not a parent of relation \"%s\"",
11221                                                 RelationGetRelationName(parent_rel),
11222                                                 RelationGetRelationName(child_rel))));
11223         }
11224
11225         /*
11226          * Search through child columns looking for ones matching parent rel
11227          */
11228         catalogRelation = heap_open(AttributeRelationId, RowExclusiveLock);
11229         ScanKeyInit(&key[0],
11230                                 Anum_pg_attribute_attrelid,
11231                                 BTEqualStrategyNumber, F_OIDEQ,
11232                                 ObjectIdGetDatum(RelationGetRelid(child_rel)));
11233         scan = systable_beginscan(catalogRelation, AttributeRelidNumIndexId,
11234                                                           true, NULL, 1, key);
11235         while (HeapTupleIsValid(attributeTuple = systable_getnext(scan)))
11236         {
11237                 Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple);
11238
11239                 /* Ignore if dropped or not inherited */
11240                 if (att->attisdropped)
11241                         continue;
11242                 if (att->attinhcount <= 0)
11243                         continue;
11244
11245                 if (SearchSysCacheExistsAttName(RelationGetRelid(parent_rel),
11246                                                                                 NameStr(att->attname)))
11247                 {
11248                         /* Decrement inhcount and possibly set islocal to true */
11249                         HeapTuple       copyTuple = heap_copytuple(attributeTuple);
11250                         Form_pg_attribute copy_att = (Form_pg_attribute) GETSTRUCT(copyTuple);
11251
11252                         copy_att->attinhcount--;
11253                         if (copy_att->attinhcount == 0)
11254                                 copy_att->attislocal = true;
11255
11256                         CatalogTupleUpdate(catalogRelation, &copyTuple->t_self, copyTuple);
11257                         heap_freetuple(copyTuple);
11258                 }
11259         }
11260         systable_endscan(scan);
11261         heap_close(catalogRelation, RowExclusiveLock);
11262
11263         /*
11264          * Likewise, find inherited check constraints and disinherit them. To do
11265          * this, we first need a list of the names of the parent's check
11266          * constraints.  (We cheat a bit by only checking for name matches,
11267          * assuming that the expressions will match.)
11268          */
11269         catalogRelation = heap_open(ConstraintRelationId, RowExclusiveLock);
11270         ScanKeyInit(&key[0],
11271                                 Anum_pg_constraint_conrelid,
11272                                 BTEqualStrategyNumber, F_OIDEQ,
11273                                 ObjectIdGetDatum(RelationGetRelid(parent_rel)));
11274         scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
11275                                                           true, NULL, 1, key);
11276
11277         connames = NIL;
11278
11279         while (HeapTupleIsValid(constraintTuple = systable_getnext(scan)))
11280         {
11281                 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTuple);
11282
11283                 if (con->contype == CONSTRAINT_CHECK)
11284                         connames = lappend(connames, pstrdup(NameStr(con->conname)));
11285         }
11286
11287         systable_endscan(scan);
11288
11289         /* Now scan the child's constraints */
11290         ScanKeyInit(&key[0],
11291                                 Anum_pg_constraint_conrelid,
11292                                 BTEqualStrategyNumber, F_OIDEQ,
11293                                 ObjectIdGetDatum(RelationGetRelid(child_rel)));
11294         scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
11295                                                           true, NULL, 1, key);
11296
11297         while (HeapTupleIsValid(constraintTuple = systable_getnext(scan)))
11298         {
11299                 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTuple);
11300                 bool            match;
11301                 ListCell   *lc;
11302
11303                 if (con->contype != CONSTRAINT_CHECK)
11304                         continue;
11305
11306                 match = false;
11307                 foreach(lc, connames)
11308                 {
11309                         if (strcmp(NameStr(con->conname), (char *) lfirst(lc)) == 0)
11310                         {
11311                                 match = true;
11312                                 break;
11313                         }
11314                 }
11315
11316                 if (match)
11317                 {
11318                         /* Decrement inhcount and possibly set islocal to true */
11319                         HeapTuple       copyTuple = heap_copytuple(constraintTuple);
11320                         Form_pg_constraint copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
11321
11322                         if (copy_con->coninhcount <= 0)         /* shouldn't happen */
11323                                 elog(ERROR, "relation %u has non-inherited constraint \"%s\"",
11324                                          RelationGetRelid(child_rel), NameStr(copy_con->conname));
11325
11326                         copy_con->coninhcount--;
11327                         if (copy_con->coninhcount == 0)
11328                                 copy_con->conislocal = true;
11329
11330                         CatalogTupleUpdate(catalogRelation, &copyTuple->t_self, copyTuple);
11331                         heap_freetuple(copyTuple);
11332                 }
11333         }
11334
11335         systable_endscan(scan);
11336         heap_close(catalogRelation, RowExclusiveLock);
11337
11338         drop_parent_dependency(RelationGetRelid(child_rel),
11339                                                    RelationRelationId,
11340                                                    RelationGetRelid(parent_rel));
11341
11342         /*
11343          * Post alter hook of this inherits. Since object_access_hook doesn't take
11344          * multiple object identifiers, we relay oid of parent relation using
11345          * auxiliary_id argument.
11346          */
11347         InvokeObjectPostAlterHookArg(InheritsRelationId,
11348                                                                  RelationGetRelid(child_rel), 0,
11349                                                                  RelationGetRelid(parent_rel), false);
11350 }
11351
11352 /*
11353  * Drop the dependency created by StoreCatalogInheritance1 (CREATE TABLE
11354  * INHERITS/ALTER TABLE INHERIT -- refclassid will be RelationRelationId) or
11355  * heap_create_with_catalog (CREATE TABLE OF/ALTER TABLE OF -- refclassid will
11356  * be TypeRelationId).  There's no convenient way to do this, so go trawling
11357  * through pg_depend.
11358  */
11359 static void
11360 drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid)
11361 {
11362         Relation        catalogRelation;
11363         SysScanDesc scan;
11364         ScanKeyData key[3];
11365         HeapTuple       depTuple;
11366
11367         catalogRelation = heap_open(DependRelationId, RowExclusiveLock);
11368
11369         ScanKeyInit(&key[0],
11370                                 Anum_pg_depend_classid,
11371                                 BTEqualStrategyNumber, F_OIDEQ,
11372                                 ObjectIdGetDatum(RelationRelationId));
11373         ScanKeyInit(&key[1],
11374                                 Anum_pg_depend_objid,
11375                                 BTEqualStrategyNumber, F_OIDEQ,
11376                                 ObjectIdGetDatum(relid));
11377         ScanKeyInit(&key[2],
11378                                 Anum_pg_depend_objsubid,
11379                                 BTEqualStrategyNumber, F_INT4EQ,
11380                                 Int32GetDatum(0));
11381
11382         scan = systable_beginscan(catalogRelation, DependDependerIndexId, true,
11383                                                           NULL, 3, key);
11384
11385         while (HeapTupleIsValid(depTuple = systable_getnext(scan)))
11386         {
11387                 Form_pg_depend dep = (Form_pg_depend) GETSTRUCT(depTuple);
11388
11389                 if (dep->refclassid == refclassid &&
11390                         dep->refobjid == refobjid &&
11391                         dep->refobjsubid == 0 &&
11392                         dep->deptype == DEPENDENCY_NORMAL)
11393                         CatalogTupleDelete(catalogRelation, &depTuple->t_self);
11394         }
11395
11396         systable_endscan(scan);
11397         heap_close(catalogRelation, RowExclusiveLock);
11398 }
11399
11400 /*
11401  * ALTER TABLE OF
11402  *
11403  * Attach a table to a composite type, as though it had been created with CREATE
11404  * TABLE OF.  All attname, atttypid, atttypmod and attcollation must match.  The
11405  * subject table must not have inheritance parents.  These restrictions ensure
11406  * that you cannot create a configuration impossible with CREATE TABLE OF alone.
11407  *
11408  * The address of the type is returned.
11409  */
11410 static ObjectAddress
11411 ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
11412 {
11413         Oid                     relid = RelationGetRelid(rel);
11414         Type            typetuple;
11415         Oid                     typeid;
11416         Relation        inheritsRelation,
11417                                 relationRelation;
11418         SysScanDesc scan;
11419         ScanKeyData key;
11420         AttrNumber      table_attno,
11421                                 type_attno;
11422         TupleDesc       typeTupleDesc,
11423                                 tableTupleDesc;
11424         ObjectAddress tableobj,
11425                                 typeobj;
11426         HeapTuple       classtuple;
11427
11428         /* Validate the type. */
11429         typetuple = typenameType(NULL, ofTypename, NULL);
11430         check_of_type(typetuple);
11431         typeid = HeapTupleGetOid(typetuple);
11432
11433         /* Fail if the table has any inheritance parents. */
11434         inheritsRelation = heap_open(InheritsRelationId, AccessShareLock);
11435         ScanKeyInit(&key,
11436                                 Anum_pg_inherits_inhrelid,
11437                                 BTEqualStrategyNumber, F_OIDEQ,
11438                                 ObjectIdGetDatum(relid));
11439         scan = systable_beginscan(inheritsRelation, InheritsRelidSeqnoIndexId,
11440                                                           true, NULL, 1, &key);
11441         if (HeapTupleIsValid(systable_getnext(scan)))
11442                 ereport(ERROR,
11443                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11444                                  errmsg("typed tables cannot inherit")));
11445         systable_endscan(scan);
11446         heap_close(inheritsRelation, AccessShareLock);
11447
11448         /*
11449          * Check the tuple descriptors for compatibility.  Unlike inheritance, we
11450          * require that the order also match.  However, attnotnull need not match.
11451          * Also unlike inheritance, we do not require matching relhasoids.
11452          */
11453         typeTupleDesc = lookup_rowtype_tupdesc(typeid, -1);
11454         tableTupleDesc = RelationGetDescr(rel);
11455         table_attno = 1;
11456         for (type_attno = 1; type_attno <= typeTupleDesc->natts; type_attno++)
11457         {
11458                 Form_pg_attribute type_attr,
11459                                         table_attr;
11460                 const char *type_attname,
11461                                    *table_attname;
11462
11463                 /* Get the next non-dropped type attribute. */
11464                 type_attr = typeTupleDesc->attrs[type_attno - 1];
11465                 if (type_attr->attisdropped)
11466                         continue;
11467                 type_attname = NameStr(type_attr->attname);
11468
11469                 /* Get the next non-dropped table attribute. */
11470                 do
11471                 {
11472                         if (table_attno > tableTupleDesc->natts)
11473                                 ereport(ERROR,
11474                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
11475                                                  errmsg("table is missing column \"%s\"",
11476                                                                 type_attname)));
11477                         table_attr = tableTupleDesc->attrs[table_attno++ - 1];
11478                 } while (table_attr->attisdropped);
11479                 table_attname = NameStr(table_attr->attname);
11480
11481                 /* Compare name. */
11482                 if (strncmp(table_attname, type_attname, NAMEDATALEN) != 0)
11483                         ereport(ERROR,
11484                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
11485                                  errmsg("table has column \"%s\" where type requires \"%s\"",
11486                                                 table_attname, type_attname)));
11487
11488                 /* Compare type. */
11489                 if (table_attr->atttypid != type_attr->atttypid ||
11490                         table_attr->atttypmod != type_attr->atttypmod ||
11491                         table_attr->attcollation != type_attr->attcollation)
11492                         ereport(ERROR,
11493                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
11494                                   errmsg("table \"%s\" has different type for column \"%s\"",
11495                                                  RelationGetRelationName(rel), type_attname)));
11496         }
11497         DecrTupleDescRefCount(typeTupleDesc);
11498
11499         /* Any remaining columns at the end of the table had better be dropped. */
11500         for (; table_attno <= tableTupleDesc->natts; table_attno++)
11501         {
11502                 Form_pg_attribute table_attr = tableTupleDesc->attrs[table_attno - 1];
11503
11504                 if (!table_attr->attisdropped)
11505                         ereport(ERROR,
11506                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
11507                                          errmsg("table has extra column \"%s\"",
11508                                                         NameStr(table_attr->attname))));
11509         }
11510
11511         /* If the table was already typed, drop the existing dependency. */
11512         if (rel->rd_rel->reloftype)
11513                 drop_parent_dependency(relid, TypeRelationId, rel->rd_rel->reloftype);
11514
11515         /* Record a dependency on the new type. */
11516         tableobj.classId = RelationRelationId;
11517         tableobj.objectId = relid;
11518         tableobj.objectSubId = 0;
11519         typeobj.classId = TypeRelationId;
11520         typeobj.objectId = typeid;
11521         typeobj.objectSubId = 0;
11522         recordDependencyOn(&tableobj, &typeobj, DEPENDENCY_NORMAL);
11523
11524         /* Update pg_class.reloftype */
11525         relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
11526         classtuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
11527         if (!HeapTupleIsValid(classtuple))
11528                 elog(ERROR, "cache lookup failed for relation %u", relid);
11529         ((Form_pg_class) GETSTRUCT(classtuple))->reloftype = typeid;
11530         CatalogTupleUpdate(relationRelation, &classtuple->t_self, classtuple);
11531
11532         InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
11533
11534         heap_freetuple(classtuple);
11535         heap_close(relationRelation, RowExclusiveLock);
11536
11537         ReleaseSysCache(typetuple);
11538
11539         return typeobj;
11540 }
11541
11542 /*
11543  * ALTER TABLE NOT OF
11544  *
11545  * Detach a typed table from its originating type.  Just clear reloftype and
11546  * remove the dependency.
11547  */
11548 static void
11549 ATExecDropOf(Relation rel, LOCKMODE lockmode)
11550 {
11551         Oid                     relid = RelationGetRelid(rel);
11552         Relation        relationRelation;
11553         HeapTuple       tuple;
11554
11555         if (!OidIsValid(rel->rd_rel->reloftype))
11556                 ereport(ERROR,
11557                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11558                                  errmsg("\"%s\" is not a typed table",
11559                                                 RelationGetRelationName(rel))));
11560
11561         /*
11562          * We don't bother to check ownership of the type --- ownership of the
11563          * table is presumed enough rights.  No lock required on the type, either.
11564          */
11565
11566         drop_parent_dependency(relid, TypeRelationId, rel->rd_rel->reloftype);
11567
11568         /* Clear pg_class.reloftype */
11569         relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
11570         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
11571         if (!HeapTupleIsValid(tuple))
11572                 elog(ERROR, "cache lookup failed for relation %u", relid);
11573         ((Form_pg_class) GETSTRUCT(tuple))->reloftype = InvalidOid;
11574         CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
11575
11576         InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
11577
11578         heap_freetuple(tuple);
11579         heap_close(relationRelation, RowExclusiveLock);
11580 }
11581
11582 /*
11583  * relation_mark_replica_identity: Update a table's replica identity
11584  *
11585  * Iff ri_type = REPLICA_IDENTITY_INDEX, indexOid must be the Oid of a suitable
11586  * index. Otherwise, it should be InvalidOid.
11587  */
11588 static void
11589 relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid,
11590                                                            bool is_internal)
11591 {
11592         Relation        pg_index;
11593         Relation        pg_class;
11594         HeapTuple       pg_class_tuple;
11595         HeapTuple       pg_index_tuple;
11596         Form_pg_class pg_class_form;
11597         Form_pg_index pg_index_form;
11598
11599         ListCell   *index;
11600
11601         /*
11602          * Check whether relreplident has changed, and update it if so.
11603          */
11604         pg_class = heap_open(RelationRelationId, RowExclusiveLock);
11605         pg_class_tuple = SearchSysCacheCopy1(RELOID,
11606                                                                         ObjectIdGetDatum(RelationGetRelid(rel)));
11607         if (!HeapTupleIsValid(pg_class_tuple))
11608                 elog(ERROR, "cache lookup failed for relation \"%s\"",
11609                          RelationGetRelationName(rel));
11610         pg_class_form = (Form_pg_class) GETSTRUCT(pg_class_tuple);
11611         if (pg_class_form->relreplident != ri_type)
11612         {
11613                 pg_class_form->relreplident = ri_type;
11614                 CatalogTupleUpdate(pg_class, &pg_class_tuple->t_self, pg_class_tuple);
11615         }
11616         heap_close(pg_class, RowExclusiveLock);
11617         heap_freetuple(pg_class_tuple);
11618
11619         /*
11620          * Check whether the correct index is marked indisreplident; if so, we're
11621          * done.
11622          */
11623         if (OidIsValid(indexOid))
11624         {
11625                 Assert(ri_type == REPLICA_IDENTITY_INDEX);
11626
11627                 pg_index_tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexOid));
11628                 if (!HeapTupleIsValid(pg_index_tuple))
11629                         elog(ERROR, "cache lookup failed for index %u", indexOid);
11630                 pg_index_form = (Form_pg_index) GETSTRUCT(pg_index_tuple);
11631
11632                 if (pg_index_form->indisreplident)
11633                 {
11634                         ReleaseSysCache(pg_index_tuple);
11635                         return;
11636                 }
11637                 ReleaseSysCache(pg_index_tuple);
11638         }
11639
11640         /*
11641          * Clear the indisreplident flag from any index that had it previously,
11642          * and set it for any index that should have it now.
11643          */
11644         pg_index = heap_open(IndexRelationId, RowExclusiveLock);
11645         foreach(index, RelationGetIndexList(rel))
11646         {
11647                 Oid                     thisIndexOid = lfirst_oid(index);
11648                 bool            dirty = false;
11649
11650                 pg_index_tuple = SearchSysCacheCopy1(INDEXRELID,
11651                                                                                          ObjectIdGetDatum(thisIndexOid));
11652                 if (!HeapTupleIsValid(pg_index_tuple))
11653                         elog(ERROR, "cache lookup failed for index %u", thisIndexOid);
11654                 pg_index_form = (Form_pg_index) GETSTRUCT(pg_index_tuple);
11655
11656                 /*
11657                  * Unset the bit if set.  We know it's wrong because we checked this
11658                  * earlier.
11659                  */
11660                 if (pg_index_form->indisreplident)
11661                 {
11662                         dirty = true;
11663                         pg_index_form->indisreplident = false;
11664                 }
11665                 else if (thisIndexOid == indexOid)
11666                 {
11667                         dirty = true;
11668                         pg_index_form->indisreplident = true;
11669                 }
11670
11671                 if (dirty)
11672                 {
11673                         CatalogTupleUpdate(pg_index, &pg_index_tuple->t_self, pg_index_tuple);
11674                         InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
11675                                                                                  InvalidOid, is_internal);
11676                 }
11677                 heap_freetuple(pg_index_tuple);
11678         }
11679
11680         heap_close(pg_index, RowExclusiveLock);
11681 }
11682
11683 /*
11684  * ALTER TABLE <name> REPLICA IDENTITY ...
11685  */
11686 static void
11687 ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode)
11688 {
11689         Oid                     indexOid;
11690         Relation        indexRel;
11691         int                     key;
11692
11693         if (stmt->identity_type == REPLICA_IDENTITY_DEFAULT)
11694         {
11695                 relation_mark_replica_identity(rel, stmt->identity_type, InvalidOid, true);
11696                 return;
11697         }
11698         else if (stmt->identity_type == REPLICA_IDENTITY_FULL)
11699         {
11700                 relation_mark_replica_identity(rel, stmt->identity_type, InvalidOid, true);
11701                 return;
11702         }
11703         else if (stmt->identity_type == REPLICA_IDENTITY_NOTHING)
11704         {
11705                 relation_mark_replica_identity(rel, stmt->identity_type, InvalidOid, true);
11706                 return;
11707         }
11708         else if (stmt->identity_type == REPLICA_IDENTITY_INDEX)
11709         {
11710                  /* fallthrough */ ;
11711         }
11712         else
11713                 elog(ERROR, "unexpected identity type %u", stmt->identity_type);
11714
11715
11716         /* Check that the index exists */
11717         indexOid = get_relname_relid(stmt->name, rel->rd_rel->relnamespace);
11718         if (!OidIsValid(indexOid))
11719                 ereport(ERROR,
11720                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
11721                                  errmsg("index \"%s\" for table \"%s\" does not exist",
11722                                                 stmt->name, RelationGetRelationName(rel))));
11723
11724         indexRel = index_open(indexOid, ShareLock);
11725
11726         /* Check that the index is on the relation we're altering. */
11727         if (indexRel->rd_index == NULL ||
11728                 indexRel->rd_index->indrelid != RelationGetRelid(rel))
11729                 ereport(ERROR,
11730                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11731                                  errmsg("\"%s\" is not an index for table \"%s\"",
11732                                                 RelationGetRelationName(indexRel),
11733                                                 RelationGetRelationName(rel))));
11734         /* The AM must support uniqueness, and the index must in fact be unique. */
11735         if (!indexRel->rd_amroutine->amcanunique ||
11736                 !indexRel->rd_index->indisunique)
11737                 ereport(ERROR,
11738                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11739                          errmsg("cannot use non-unique index \"%s\" as replica identity",
11740                                         RelationGetRelationName(indexRel))));
11741         /* Deferred indexes are not guaranteed to be always unique. */
11742         if (!indexRel->rd_index->indimmediate)
11743                 ereport(ERROR,
11744                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11745                   errmsg("cannot use non-immediate index \"%s\" as replica identity",
11746                                  RelationGetRelationName(indexRel))));
11747         /* Expression indexes aren't supported. */
11748         if (RelationGetIndexExpressions(indexRel) != NIL)
11749                 ereport(ERROR,
11750                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11751                          errmsg("cannot use expression index \"%s\" as replica identity",
11752                                         RelationGetRelationName(indexRel))));
11753         /* Predicate indexes aren't supported. */
11754         if (RelationGetIndexPredicate(indexRel) != NIL)
11755                 ereport(ERROR,
11756                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11757                                  errmsg("cannot use partial index \"%s\" as replica identity",
11758                                                 RelationGetRelationName(indexRel))));
11759         /* And neither are invalid indexes. */
11760         if (!IndexIsValid(indexRel->rd_index))
11761                 ereport(ERROR,
11762                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11763                                  errmsg("cannot use invalid index \"%s\" as replica identity",
11764                                                 RelationGetRelationName(indexRel))));
11765
11766         /* Check index for nullable columns. */
11767         for (key = 0; key < indexRel->rd_index->indnatts; key++)
11768         {
11769                 int16           attno = indexRel->rd_index->indkey.values[key];
11770                 Form_pg_attribute attr;
11771
11772                 /* Allow OID column to be indexed; it's certainly not nullable */
11773                 if (attno == ObjectIdAttributeNumber)
11774                         continue;
11775
11776                 /*
11777                  * Reject any other system columns.  (Going forward, we'll disallow
11778                  * indexes containing such columns in the first place, but they might
11779                  * exist in older branches.)
11780                  */
11781                 if (attno <= 0)
11782                         ereport(ERROR,
11783                                         (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
11784                                          errmsg("index \"%s\" cannot be used as replica identity because column %d is a system column",
11785                                                         RelationGetRelationName(indexRel), attno)));
11786
11787                 attr = rel->rd_att->attrs[attno - 1];
11788                 if (!attr->attnotnull)
11789                         ereport(ERROR,
11790                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11791                                          errmsg("index \"%s\" cannot be used as replica identity because column \"%s\" is nullable",
11792                                                         RelationGetRelationName(indexRel),
11793                                                         NameStr(attr->attname))));
11794         }
11795
11796         /* This index is suitable for use as a replica identity. Mark it. */
11797         relation_mark_replica_identity(rel, stmt->identity_type, indexOid, true);
11798
11799         index_close(indexRel, NoLock);
11800 }
11801
11802 /*
11803  * ALTER TABLE ENABLE/DISABLE ROW LEVEL SECURITY
11804  */
11805 static void
11806 ATExecEnableRowSecurity(Relation rel)
11807 {
11808         Relation        pg_class;
11809         Oid                     relid;
11810         HeapTuple       tuple;
11811
11812         relid = RelationGetRelid(rel);
11813
11814         pg_class = heap_open(RelationRelationId, RowExclusiveLock);
11815
11816         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
11817
11818         if (!HeapTupleIsValid(tuple))
11819                 elog(ERROR, "cache lookup failed for relation %u", relid);
11820
11821         ((Form_pg_class) GETSTRUCT(tuple))->relrowsecurity = true;
11822         CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
11823
11824         heap_close(pg_class, RowExclusiveLock);
11825         heap_freetuple(tuple);
11826 }
11827
11828 static void
11829 ATExecDisableRowSecurity(Relation rel)
11830 {
11831         Relation        pg_class;
11832         Oid                     relid;
11833         HeapTuple       tuple;
11834
11835         relid = RelationGetRelid(rel);
11836
11837         /* Pull the record for this relation and update it */
11838         pg_class = heap_open(RelationRelationId, RowExclusiveLock);
11839
11840         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
11841
11842         if (!HeapTupleIsValid(tuple))
11843                 elog(ERROR, "cache lookup failed for relation %u", relid);
11844
11845         ((Form_pg_class) GETSTRUCT(tuple))->relrowsecurity = false;
11846         CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
11847
11848         heap_close(pg_class, RowExclusiveLock);
11849         heap_freetuple(tuple);
11850 }
11851
11852 /*
11853  * ALTER TABLE FORCE/NO FORCE ROW LEVEL SECURITY
11854  */
11855 static void
11856 ATExecForceNoForceRowSecurity(Relation rel, bool force_rls)
11857 {
11858         Relation        pg_class;
11859         Oid                     relid;
11860         HeapTuple       tuple;
11861
11862         relid = RelationGetRelid(rel);
11863
11864         pg_class = heap_open(RelationRelationId, RowExclusiveLock);
11865
11866         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
11867
11868         if (!HeapTupleIsValid(tuple))
11869                 elog(ERROR, "cache lookup failed for relation %u", relid);
11870
11871         ((Form_pg_class) GETSTRUCT(tuple))->relforcerowsecurity = force_rls;
11872         CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
11873
11874         heap_close(pg_class, RowExclusiveLock);
11875         heap_freetuple(tuple);
11876 }
11877
11878 /*
11879  * ALTER FOREIGN TABLE <name> OPTIONS (...)
11880  */
11881 static void
11882 ATExecGenericOptions(Relation rel, List *options)
11883 {
11884         Relation        ftrel;
11885         ForeignServer *server;
11886         ForeignDataWrapper *fdw;
11887         HeapTuple       tuple;
11888         bool            isnull;
11889         Datum           repl_val[Natts_pg_foreign_table];
11890         bool            repl_null[Natts_pg_foreign_table];
11891         bool            repl_repl[Natts_pg_foreign_table];
11892         Datum           datum;
11893         Form_pg_foreign_table tableform;
11894
11895         if (options == NIL)
11896                 return;
11897
11898         ftrel = heap_open(ForeignTableRelationId, RowExclusiveLock);
11899
11900         tuple = SearchSysCacheCopy1(FOREIGNTABLEREL, rel->rd_id);
11901         if (!HeapTupleIsValid(tuple))
11902                 ereport(ERROR,
11903                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
11904                                  errmsg("foreign table \"%s\" does not exist",
11905                                                 RelationGetRelationName(rel))));
11906         tableform = (Form_pg_foreign_table) GETSTRUCT(tuple);
11907         server = GetForeignServer(tableform->ftserver);
11908         fdw = GetForeignDataWrapper(server->fdwid);
11909
11910         memset(repl_val, 0, sizeof(repl_val));
11911         memset(repl_null, false, sizeof(repl_null));
11912         memset(repl_repl, false, sizeof(repl_repl));
11913
11914         /* Extract the current options */
11915         datum = SysCacheGetAttr(FOREIGNTABLEREL,
11916                                                         tuple,
11917                                                         Anum_pg_foreign_table_ftoptions,
11918                                                         &isnull);
11919         if (isnull)
11920                 datum = PointerGetDatum(NULL);
11921
11922         /* Transform the options */
11923         datum = transformGenericOptions(ForeignTableRelationId,
11924                                                                         datum,
11925                                                                         options,
11926                                                                         fdw->fdwvalidator);
11927
11928         if (PointerIsValid(DatumGetPointer(datum)))
11929                 repl_val[Anum_pg_foreign_table_ftoptions - 1] = datum;
11930         else
11931                 repl_null[Anum_pg_foreign_table_ftoptions - 1] = true;
11932
11933         repl_repl[Anum_pg_foreign_table_ftoptions - 1] = true;
11934
11935         /* Everything looks good - update the tuple */
11936
11937         tuple = heap_modify_tuple(tuple, RelationGetDescr(ftrel),
11938                                                           repl_val, repl_null, repl_repl);
11939
11940         CatalogTupleUpdate(ftrel, &tuple->t_self, tuple);
11941
11942         /*
11943          * Invalidate relcache so that all sessions will refresh any cached plans
11944          * that might depend on the old options.
11945          */
11946         CacheInvalidateRelcache(rel);
11947
11948         InvokeObjectPostAlterHook(ForeignTableRelationId,
11949                                                           RelationGetRelid(rel), 0);
11950
11951         heap_close(ftrel, RowExclusiveLock);
11952
11953         heap_freetuple(tuple);
11954 }
11955
11956 /*
11957  * Preparation phase for SET LOGGED/UNLOGGED
11958  *
11959  * This verifies that we're not trying to change a temp table.  Also,
11960  * existing foreign key constraints are checked to avoid ending up with
11961  * permanent tables referencing unlogged tables.
11962  *
11963  * Return value is false if the operation is a no-op (in which case the
11964  * checks are skipped), otherwise true.
11965  */
11966 static bool
11967 ATPrepChangePersistence(Relation rel, bool toLogged)
11968 {
11969         Relation        pg_constraint;
11970         HeapTuple       tuple;
11971         SysScanDesc scan;
11972         ScanKeyData skey[1];
11973
11974         /*
11975          * Disallow changing status for a temp table.  Also verify whether we can
11976          * get away with doing nothing; in such cases we don't need to run the
11977          * checks below, either.
11978          */
11979         switch (rel->rd_rel->relpersistence)
11980         {
11981                 case RELPERSISTENCE_TEMP:
11982                         ereport(ERROR,
11983                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
11984                                          errmsg("cannot change logged status of table \"%s\" because it is temporary",
11985                                                         RelationGetRelationName(rel)),
11986                                          errtable(rel)));
11987                         break;
11988                 case RELPERSISTENCE_PERMANENT:
11989                         if (toLogged)
11990                                 /* nothing to do */
11991                                 return false;
11992                         break;
11993                 case RELPERSISTENCE_UNLOGGED:
11994                         if (!toLogged)
11995                                 /* nothing to do */
11996                                 return false;
11997                         break;
11998         }
11999
12000         /*
12001          * Check that the table is not part any publication when changing to
12002          * UNLOGGED as UNLOGGED tables can't be published.
12003          */
12004         if (!toLogged &&
12005                 list_length(GetRelationPublications(RelationGetRelid(rel))) > 0)
12006                 ereport(ERROR,
12007                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
12008                                  errmsg("cannot change table \"%s\" to unlogged because it is part of a publication",
12009                                                 RelationGetRelationName(rel)),
12010                                  errdetail("Unlogged relations cannot be replicated.")));
12011
12012         /*
12013          * Check existing foreign key constraints to preserve the invariant that
12014          * permanent tables cannot reference unlogged ones.  Self-referencing
12015          * foreign keys can safely be ignored.
12016          */
12017         pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
12018
12019         /*
12020          * Scan conrelid if changing to permanent, else confrelid.  This also
12021          * determines whether a useful index exists.
12022          */
12023         ScanKeyInit(&skey[0],
12024                                 toLogged ? Anum_pg_constraint_conrelid :
12025                                 Anum_pg_constraint_confrelid,
12026                                 BTEqualStrategyNumber, F_OIDEQ,
12027                                 ObjectIdGetDatum(RelationGetRelid(rel)));
12028         scan = systable_beginscan(pg_constraint,
12029                                                           toLogged ? ConstraintRelidIndexId : InvalidOid,
12030                                                           true, NULL, 1, skey);
12031
12032         while (HeapTupleIsValid(tuple = systable_getnext(scan)))
12033         {
12034                 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
12035
12036                 if (con->contype == CONSTRAINT_FOREIGN)
12037                 {
12038                         Oid                     foreignrelid;
12039                         Relation        foreignrel;
12040
12041                         /* the opposite end of what we used as scankey */
12042                         foreignrelid = toLogged ? con->confrelid : con->conrelid;
12043
12044                         /* ignore if self-referencing */
12045                         if (RelationGetRelid(rel) == foreignrelid)
12046                                 continue;
12047
12048                         foreignrel = relation_open(foreignrelid, AccessShareLock);
12049
12050                         if (toLogged)
12051                         {
12052                                 if (foreignrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT)
12053                                         ereport(ERROR,
12054                                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
12055                                                          errmsg("could not change table \"%s\" to logged because it references unlogged table \"%s\"",
12056                                                                         RelationGetRelationName(rel),
12057                                                                         RelationGetRelationName(foreignrel)),
12058                                                          errtableconstraint(rel, NameStr(con->conname))));
12059                         }
12060                         else
12061                         {
12062                                 if (foreignrel->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT)
12063                                         ereport(ERROR,
12064                                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
12065                                                          errmsg("could not change table \"%s\" to unlogged because it references logged table \"%s\"",
12066                                                                         RelationGetRelationName(rel),
12067                                                                         RelationGetRelationName(foreignrel)),
12068                                                          errtableconstraint(rel, NameStr(con->conname))));
12069                         }
12070
12071                         relation_close(foreignrel, AccessShareLock);
12072                 }
12073         }
12074
12075         systable_endscan(scan);
12076
12077         heap_close(pg_constraint, AccessShareLock);
12078
12079         return true;
12080 }
12081
12082 /*
12083  * Execute ALTER TABLE SET SCHEMA
12084  */
12085 ObjectAddress
12086 AlterTableNamespace(AlterObjectSchemaStmt *stmt, Oid *oldschema)
12087 {
12088         Relation        rel;
12089         Oid                     relid;
12090         Oid                     oldNspOid;
12091         Oid                     nspOid;
12092         RangeVar   *newrv;
12093         ObjectAddresses *objsMoved;
12094         ObjectAddress myself;
12095
12096         relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
12097                                                                          stmt->missing_ok, false,
12098                                                                          RangeVarCallbackForAlterRelation,
12099                                                                          (void *) stmt);
12100
12101         if (!OidIsValid(relid))
12102         {
12103                 ereport(NOTICE,
12104                                 (errmsg("relation \"%s\" does not exist, skipping",
12105                                                 stmt->relation->relname)));
12106                 return InvalidObjectAddress;
12107         }
12108
12109         rel = relation_open(relid, NoLock);
12110
12111         oldNspOid = RelationGetNamespace(rel);
12112
12113         /* If it's an owned sequence, disallow moving it by itself. */
12114         if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
12115         {
12116                 Oid                     tableId;
12117                 int32           colId;
12118
12119                 if (sequenceIsOwned(relid, &tableId, &colId))
12120                         ereport(ERROR,
12121                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
12122                                  errmsg("cannot move an owned sequence into another schema"),
12123                                          errdetail("Sequence \"%s\" is linked to table \"%s\".",
12124                                                            RelationGetRelationName(rel),
12125                                                            get_rel_name(tableId))));
12126         }
12127
12128         /* Get and lock schema OID and check its permissions. */
12129         newrv = makeRangeVar(stmt->newschema, RelationGetRelationName(rel), -1);
12130         nspOid = RangeVarGetAndCheckCreationNamespace(newrv, NoLock, NULL);
12131
12132         /* common checks on switching namespaces */
12133         CheckSetNamespace(oldNspOid, nspOid);
12134
12135         objsMoved = new_object_addresses();
12136         AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
12137         free_object_addresses(objsMoved);
12138
12139         ObjectAddressSet(myself, RelationRelationId, relid);
12140
12141         if (oldschema)
12142                 *oldschema = oldNspOid;
12143
12144         /* close rel, but keep lock until commit */
12145         relation_close(rel, NoLock);
12146
12147         return myself;
12148 }
12149
12150 /*
12151  * The guts of relocating a table or materialized view to another namespace:
12152  * besides moving the relation itself, its dependent objects are relocated to
12153  * the new schema.
12154  */
12155 void
12156 AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid,
12157                                                         ObjectAddresses *objsMoved)
12158 {
12159         Relation        classRel;
12160
12161         Assert(objsMoved != NULL);
12162
12163         /* OK, modify the pg_class row and pg_depend entry */
12164         classRel = heap_open(RelationRelationId, RowExclusiveLock);
12165
12166         AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid,
12167                                                                    nspOid, true, objsMoved);
12168
12169         /* Fix the table's row type too */
12170         AlterTypeNamespaceInternal(rel->rd_rel->reltype,
12171                                                            nspOid, false, false, objsMoved);
12172
12173         /* Fix other dependent stuff */
12174         if (rel->rd_rel->relkind == RELKIND_RELATION ||
12175                 rel->rd_rel->relkind == RELKIND_MATVIEW ||
12176                 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
12177         {
12178                 AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
12179                 AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
12180                                                    objsMoved, AccessExclusiveLock);
12181                 AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
12182                                                                   false, objsMoved);
12183         }
12184
12185         heap_close(classRel, RowExclusiveLock);
12186 }
12187
12188 /*
12189  * The guts of relocating a relation to another namespace: fix the pg_class
12190  * entry, and the pg_depend entry if any.  Caller must already have
12191  * opened and write-locked pg_class.
12192  */
12193 void
12194 AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
12195                                                            Oid oldNspOid, Oid newNspOid,
12196                                                            bool hasDependEntry,
12197                                                            ObjectAddresses *objsMoved)
12198 {
12199         HeapTuple       classTup;
12200         Form_pg_class classForm;
12201         ObjectAddress thisobj;
12202         bool            already_done = false;
12203
12204         classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid));
12205         if (!HeapTupleIsValid(classTup))
12206                 elog(ERROR, "cache lookup failed for relation %u", relOid);
12207         classForm = (Form_pg_class) GETSTRUCT(classTup);
12208
12209         Assert(classForm->relnamespace == oldNspOid);
12210
12211         thisobj.classId = RelationRelationId;
12212         thisobj.objectId = relOid;
12213         thisobj.objectSubId = 0;
12214
12215         /*
12216          * If the object has already been moved, don't move it again.  If it's
12217          * already in the right place, don't move it, but still fire the object
12218          * access hook.
12219          */
12220         already_done = object_address_present(&thisobj, objsMoved);
12221         if (!already_done && oldNspOid != newNspOid)
12222         {
12223                 /* check for duplicate name (more friendly than unique-index failure) */
12224                 if (get_relname_relid(NameStr(classForm->relname),
12225                                                           newNspOid) != InvalidOid)
12226                         ereport(ERROR,
12227                                         (errcode(ERRCODE_DUPLICATE_TABLE),
12228                                          errmsg("relation \"%s\" already exists in schema \"%s\"",
12229                                                         NameStr(classForm->relname),
12230                                                         get_namespace_name(newNspOid))));
12231
12232                 /* classTup is a copy, so OK to scribble on */
12233                 classForm->relnamespace = newNspOid;
12234
12235                 CatalogTupleUpdate(classRel, &classTup->t_self, classTup);
12236
12237                 /* Update dependency on schema if caller said so */
12238                 if (hasDependEntry &&
12239                         changeDependencyFor(RelationRelationId,
12240                                                                 relOid,
12241                                                                 NamespaceRelationId,
12242                                                                 oldNspOid,
12243                                                                 newNspOid) != 1)
12244                         elog(ERROR, "failed to change schema dependency for relation \"%s\"",
12245                                  NameStr(classForm->relname));
12246         }
12247         if (!already_done)
12248         {
12249                 add_exact_object_address(&thisobj, objsMoved);
12250
12251                 InvokeObjectPostAlterHook(RelationRelationId, relOid, 0);
12252         }
12253
12254         heap_freetuple(classTup);
12255 }
12256
12257 /*
12258  * Move all indexes for the specified relation to another namespace.
12259  *
12260  * Note: we assume adequate permission checking was done by the caller,
12261  * and that the caller has a suitable lock on the owning relation.
12262  */
12263 static void
12264 AlterIndexNamespaces(Relation classRel, Relation rel,
12265                                          Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved)
12266 {
12267         List       *indexList;
12268         ListCell   *l;
12269
12270         indexList = RelationGetIndexList(rel);
12271
12272         foreach(l, indexList)
12273         {
12274                 Oid                     indexOid = lfirst_oid(l);
12275                 ObjectAddress thisobj;
12276
12277                 thisobj.classId = RelationRelationId;
12278                 thisobj.objectId = indexOid;
12279                 thisobj.objectSubId = 0;
12280
12281                 /*
12282                  * Note: currently, the index will not have its own dependency on the
12283                  * namespace, so we don't need to do changeDependencyFor(). There's no
12284                  * row type in pg_type, either.
12285                  *
12286                  * XXX this objsMoved test may be pointless -- surely we have a single
12287                  * dependency link from a relation to each index?
12288                  */
12289                 if (!object_address_present(&thisobj, objsMoved))
12290                 {
12291                         AlterRelationNamespaceInternal(classRel, indexOid,
12292                                                                                    oldNspOid, newNspOid,
12293                                                                                    false, objsMoved);
12294                         add_exact_object_address(&thisobj, objsMoved);
12295                 }
12296         }
12297
12298         list_free(indexList);
12299 }
12300
12301 /*
12302  * Move all SERIAL-column sequences of the specified relation to another
12303  * namespace.
12304  *
12305  * Note: we assume adequate permission checking was done by the caller,
12306  * and that the caller has a suitable lock on the owning relation.
12307  */
12308 static void
12309 AlterSeqNamespaces(Relation classRel, Relation rel,
12310                                    Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved,
12311                                    LOCKMODE lockmode)
12312 {
12313         Relation        depRel;
12314         SysScanDesc scan;
12315         ScanKeyData key[2];
12316         HeapTuple       tup;
12317
12318         /*
12319          * SERIAL sequences are those having an auto dependency on one of the
12320          * table's columns (we don't care *which* column, exactly).
12321          */
12322         depRel = heap_open(DependRelationId, AccessShareLock);
12323
12324         ScanKeyInit(&key[0],
12325                                 Anum_pg_depend_refclassid,
12326                                 BTEqualStrategyNumber, F_OIDEQ,
12327                                 ObjectIdGetDatum(RelationRelationId));
12328         ScanKeyInit(&key[1],
12329                                 Anum_pg_depend_refobjid,
12330                                 BTEqualStrategyNumber, F_OIDEQ,
12331                                 ObjectIdGetDatum(RelationGetRelid(rel)));
12332         /* we leave refobjsubid unspecified */
12333
12334         scan = systable_beginscan(depRel, DependReferenceIndexId, true,
12335                                                           NULL, 2, key);
12336
12337         while (HeapTupleIsValid(tup = systable_getnext(scan)))
12338         {
12339                 Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
12340                 Relation        seqRel;
12341
12342                 /* skip dependencies other than auto dependencies on columns */
12343                 if (depForm->refobjsubid == 0 ||
12344                         depForm->classid != RelationRelationId ||
12345                         depForm->objsubid != 0 ||
12346                         depForm->deptype != DEPENDENCY_AUTO)
12347                         continue;
12348
12349                 /* Use relation_open just in case it's an index */
12350                 seqRel = relation_open(depForm->objid, lockmode);
12351
12352                 /* skip non-sequence relations */
12353                 if (RelationGetForm(seqRel)->relkind != RELKIND_SEQUENCE)
12354                 {
12355                         /* No need to keep the lock */
12356                         relation_close(seqRel, lockmode);
12357                         continue;
12358                 }
12359
12360                 /* Fix the pg_class and pg_depend entries */
12361                 AlterRelationNamespaceInternal(classRel, depForm->objid,
12362                                                                            oldNspOid, newNspOid,
12363                                                                            true, objsMoved);
12364
12365                 /*
12366                  * Sequences have entries in pg_type. We need to be careful to move
12367                  * them to the new namespace, too.
12368                  */
12369                 AlterTypeNamespaceInternal(RelationGetForm(seqRel)->reltype,
12370                                                                    newNspOid, false, false, objsMoved);
12371
12372                 /* Now we can close it.  Keep the lock till end of transaction. */
12373                 relation_close(seqRel, NoLock);
12374         }
12375
12376         systable_endscan(scan);
12377
12378         relation_close(depRel, AccessShareLock);
12379 }
12380
12381
12382 /*
12383  * This code supports
12384  *      CREATE TEMP TABLE ... ON COMMIT { DROP | PRESERVE ROWS | DELETE ROWS }
12385  *
12386  * Because we only support this for TEMP tables, it's sufficient to remember
12387  * the state in a backend-local data structure.
12388  */
12389
12390 /*
12391  * Register a newly-created relation's ON COMMIT action.
12392  */
12393 void
12394 register_on_commit_action(Oid relid, OnCommitAction action)
12395 {
12396         OnCommitItem *oc;
12397         MemoryContext oldcxt;
12398
12399         /*
12400          * We needn't bother registering the relation unless there is an ON COMMIT
12401          * action we need to take.
12402          */
12403         if (action == ONCOMMIT_NOOP || action == ONCOMMIT_PRESERVE_ROWS)
12404                 return;
12405
12406         oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
12407
12408         oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
12409         oc->relid = relid;
12410         oc->oncommit = action;
12411         oc->creating_subid = GetCurrentSubTransactionId();
12412         oc->deleting_subid = InvalidSubTransactionId;
12413
12414         on_commits = lcons(oc, on_commits);
12415
12416         MemoryContextSwitchTo(oldcxt);
12417 }
12418
12419 /*
12420  * Unregister any ON COMMIT action when a relation is deleted.
12421  *
12422  * Actually, we only mark the OnCommitItem entry as to be deleted after commit.
12423  */
12424 void
12425 remove_on_commit_action(Oid relid)
12426 {
12427         ListCell   *l;
12428
12429         foreach(l, on_commits)
12430         {
12431                 OnCommitItem *oc = (OnCommitItem *) lfirst(l);
12432
12433                 if (oc->relid == relid)
12434                 {
12435                         oc->deleting_subid = GetCurrentSubTransactionId();
12436                         break;
12437                 }
12438         }
12439 }
12440
12441 /*
12442  * Perform ON COMMIT actions.
12443  *
12444  * This is invoked just before actually committing, since it's possible
12445  * to encounter errors.
12446  */
12447 void
12448 PreCommit_on_commit_actions(void)
12449 {
12450         ListCell   *l;
12451         List       *oids_to_truncate = NIL;
12452
12453         foreach(l, on_commits)
12454         {
12455                 OnCommitItem *oc = (OnCommitItem *) lfirst(l);
12456
12457                 /* Ignore entry if already dropped in this xact */
12458                 if (oc->deleting_subid != InvalidSubTransactionId)
12459                         continue;
12460
12461                 switch (oc->oncommit)
12462                 {
12463                         case ONCOMMIT_NOOP:
12464                         case ONCOMMIT_PRESERVE_ROWS:
12465                                 /* Do nothing (there shouldn't be such entries, actually) */
12466                                 break;
12467                         case ONCOMMIT_DELETE_ROWS:
12468
12469                                 /*
12470                                  * If this transaction hasn't accessed any temporary
12471                                  * relations, we can skip truncating ON COMMIT DELETE ROWS
12472                                  * tables, as they must still be empty.
12473                                  */
12474                                 if ((MyXactFlags & XACT_FLAGS_ACCESSEDTEMPREL))
12475                                         oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
12476                                 break;
12477                         case ONCOMMIT_DROP:
12478                                 {
12479                                         ObjectAddress object;
12480
12481                                         object.classId = RelationRelationId;
12482                                         object.objectId = oc->relid;
12483                                         object.objectSubId = 0;
12484
12485                                         /*
12486                                          * Since this is an automatic drop, rather than one
12487                                          * directly initiated by the user, we pass the
12488                                          * PERFORM_DELETION_INTERNAL flag.
12489                                          */
12490                                         performDeletion(&object,
12491                                                                         DROP_CASCADE, PERFORM_DELETION_INTERNAL);
12492
12493                                         /*
12494                                          * Note that table deletion will call
12495                                          * remove_on_commit_action, so the entry should get marked
12496                                          * as deleted.
12497                                          */
12498                                         Assert(oc->deleting_subid != InvalidSubTransactionId);
12499                                         break;
12500                                 }
12501                 }
12502         }
12503         if (oids_to_truncate != NIL)
12504         {
12505                 heap_truncate(oids_to_truncate);
12506                 CommandCounterIncrement();              /* XXX needed? */
12507         }
12508 }
12509
12510 /*
12511  * Post-commit or post-abort cleanup for ON COMMIT management.
12512  *
12513  * All we do here is remove no-longer-needed OnCommitItem entries.
12514  *
12515  * During commit, remove entries that were deleted during this transaction;
12516  * during abort, remove those created during this transaction.
12517  */
12518 void
12519 AtEOXact_on_commit_actions(bool isCommit)
12520 {
12521         ListCell   *cur_item;
12522         ListCell   *prev_item;
12523
12524         prev_item = NULL;
12525         cur_item = list_head(on_commits);
12526
12527         while (cur_item != NULL)
12528         {
12529                 OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
12530
12531                 if (isCommit ? oc->deleting_subid != InvalidSubTransactionId :
12532                         oc->creating_subid != InvalidSubTransactionId)
12533                 {
12534                         /* cur_item must be removed */
12535                         on_commits = list_delete_cell(on_commits, cur_item, prev_item);
12536                         pfree(oc);
12537                         if (prev_item)
12538                                 cur_item = lnext(prev_item);
12539                         else
12540                                 cur_item = list_head(on_commits);
12541                 }
12542                 else
12543                 {
12544                         /* cur_item must be preserved */
12545                         oc->creating_subid = InvalidSubTransactionId;
12546                         oc->deleting_subid = InvalidSubTransactionId;
12547                         prev_item = cur_item;
12548                         cur_item = lnext(prev_item);
12549                 }
12550         }
12551 }
12552
12553 /*
12554  * Post-subcommit or post-subabort cleanup for ON COMMIT management.
12555  *
12556  * During subabort, we can immediately remove entries created during this
12557  * subtransaction.  During subcommit, just relabel entries marked during
12558  * this subtransaction as being the parent's responsibility.
12559  */
12560 void
12561 AtEOSubXact_on_commit_actions(bool isCommit, SubTransactionId mySubid,
12562                                                           SubTransactionId parentSubid)
12563 {
12564         ListCell   *cur_item;
12565         ListCell   *prev_item;
12566
12567         prev_item = NULL;
12568         cur_item = list_head(on_commits);
12569
12570         while (cur_item != NULL)
12571         {
12572                 OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
12573
12574                 if (!isCommit && oc->creating_subid == mySubid)
12575                 {
12576                         /* cur_item must be removed */
12577                         on_commits = list_delete_cell(on_commits, cur_item, prev_item);
12578                         pfree(oc);
12579                         if (prev_item)
12580                                 cur_item = lnext(prev_item);
12581                         else
12582                                 cur_item = list_head(on_commits);
12583                 }
12584                 else
12585                 {
12586                         /* cur_item must be preserved */
12587                         if (oc->creating_subid == mySubid)
12588                                 oc->creating_subid = parentSubid;
12589                         if (oc->deleting_subid == mySubid)
12590                                 oc->deleting_subid = isCommit ? parentSubid : InvalidSubTransactionId;
12591                         prev_item = cur_item;
12592                         cur_item = lnext(prev_item);
12593                 }
12594         }
12595 }
12596
12597 /*
12598  * This is intended as a callback for RangeVarGetRelidExtended().  It allows
12599  * the relation to be locked only if (1) it's a plain table, materialized
12600  * view, or TOAST table and (2) the current user is the owner (or the
12601  * superuser).  This meets the permission-checking needs of CLUSTER, REINDEX
12602  * TABLE, and REFRESH MATERIALIZED VIEW; we expose it here so that it can be
12603  * used by all.
12604  */
12605 void
12606 RangeVarCallbackOwnsTable(const RangeVar *relation,
12607                                                   Oid relId, Oid oldRelId, void *arg)
12608 {
12609         char            relkind;
12610
12611         /* Nothing to do if the relation was not found. */
12612         if (!OidIsValid(relId))
12613                 return;
12614
12615         /*
12616          * If the relation does exist, check whether it's an index.  But note that
12617          * the relation might have been dropped between the time we did the name
12618          * lookup and now.  In that case, there's nothing to do.
12619          */
12620         relkind = get_rel_relkind(relId);
12621         if (!relkind)
12622                 return;
12623         if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
12624                 relkind != RELKIND_MATVIEW && relkind != RELKIND_PARTITIONED_TABLE)
12625                 ereport(ERROR,
12626                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12627                                  errmsg("\"%s\" is not a table or materialized view", relation->relname)));
12628
12629         /* Check permissions */
12630         if (!pg_class_ownercheck(relId, GetUserId()))
12631                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, relation->relname);
12632 }
12633
12634 /*
12635  * Callback to RangeVarGetRelidExtended(), similar to
12636  * RangeVarCallbackOwnsTable() but without checks on the type of the relation.
12637  */
12638 void
12639 RangeVarCallbackOwnsRelation(const RangeVar *relation,
12640                                                          Oid relId, Oid oldRelId, void *arg)
12641 {
12642         HeapTuple       tuple;
12643
12644         /* Nothing to do if the relation was not found. */
12645         if (!OidIsValid(relId))
12646                 return;
12647
12648         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relId));
12649         if (!HeapTupleIsValid(tuple))           /* should not happen */
12650                 elog(ERROR, "cache lookup failed for relation %u", relId);
12651
12652         if (!pg_class_ownercheck(relId, GetUserId()))
12653                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
12654                                            relation->relname);
12655
12656         if (!allowSystemTableMods &&
12657                 IsSystemClass(relId, (Form_pg_class) GETSTRUCT(tuple)))
12658                 ereport(ERROR,
12659                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
12660                                  errmsg("permission denied: \"%s\" is a system catalog",
12661                                                 relation->relname)));
12662
12663         ReleaseSysCache(tuple);
12664 }
12665
12666 /*
12667  * Common RangeVarGetRelid callback for rename, set schema, and alter table
12668  * processing.
12669  */
12670 static void
12671 RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
12672                                                                  void *arg)
12673 {
12674         Node       *stmt = (Node *) arg;
12675         ObjectType      reltype;
12676         HeapTuple       tuple;
12677         Form_pg_class classform;
12678         AclResult       aclresult;
12679         char            relkind;
12680
12681         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
12682         if (!HeapTupleIsValid(tuple))
12683                 return;                                 /* concurrently dropped */
12684         classform = (Form_pg_class) GETSTRUCT(tuple);
12685         relkind = classform->relkind;
12686
12687         /* Must own relation. */
12688         if (!pg_class_ownercheck(relid, GetUserId()))
12689                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, rv->relname);
12690
12691         /* No system table modifications unless explicitly allowed. */
12692         if (!allowSystemTableMods && IsSystemClass(relid, classform))
12693                 ereport(ERROR,
12694                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
12695                                  errmsg("permission denied: \"%s\" is a system catalog",
12696                                                 rv->relname)));
12697
12698         /*
12699          * Extract the specified relation type from the statement parse tree.
12700          *
12701          * Also, for ALTER .. RENAME, check permissions: the user must (still)
12702          * have CREATE rights on the containing namespace.
12703          */
12704         if (IsA(stmt, RenameStmt))
12705         {
12706                 aclresult = pg_namespace_aclcheck(classform->relnamespace,
12707                                                                                   GetUserId(), ACL_CREATE);
12708                 if (aclresult != ACLCHECK_OK)
12709                         aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
12710                                                    get_namespace_name(classform->relnamespace));
12711                 reltype = ((RenameStmt *) stmt)->renameType;
12712         }
12713         else if (IsA(stmt, AlterObjectSchemaStmt))
12714                 reltype = ((AlterObjectSchemaStmt *) stmt)->objectType;
12715
12716         else if (IsA(stmt, AlterTableStmt))
12717                 reltype = ((AlterTableStmt *) stmt)->relkind;
12718         else
12719         {
12720                 reltype = OBJECT_TABLE; /* placate compiler */
12721                 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
12722         }
12723
12724         /*
12725          * For compatibility with prior releases, we allow ALTER TABLE to be used
12726          * with most other types of relations (but not composite types). We allow
12727          * similar flexibility for ALTER INDEX in the case of RENAME, but not
12728          * otherwise.  Otherwise, the user must select the correct form of the
12729          * command for the relation at issue.
12730          */
12731         if (reltype == OBJECT_SEQUENCE && relkind != RELKIND_SEQUENCE)
12732                 ereport(ERROR,
12733                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12734                                  errmsg("\"%s\" is not a sequence", rv->relname)));
12735
12736         if (reltype == OBJECT_VIEW && relkind != RELKIND_VIEW)
12737                 ereport(ERROR,
12738                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12739                                  errmsg("\"%s\" is not a view", rv->relname)));
12740
12741         if (reltype == OBJECT_MATVIEW && relkind != RELKIND_MATVIEW)
12742                 ereport(ERROR,
12743                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12744                                  errmsg("\"%s\" is not a materialized view", rv->relname)));
12745
12746         if (reltype == OBJECT_FOREIGN_TABLE && relkind != RELKIND_FOREIGN_TABLE)
12747                 ereport(ERROR,
12748                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12749                                  errmsg("\"%s\" is not a foreign table", rv->relname)));
12750
12751         if (reltype == OBJECT_TYPE && relkind != RELKIND_COMPOSITE_TYPE)
12752                 ereport(ERROR,
12753                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12754                                  errmsg("\"%s\" is not a composite type", rv->relname)));
12755
12756         if (reltype == OBJECT_INDEX && relkind != RELKIND_INDEX
12757                 && !IsA(stmt, RenameStmt))
12758                 ereport(ERROR,
12759                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12760                                  errmsg("\"%s\" is not an index", rv->relname)));
12761
12762         /*
12763          * Don't allow ALTER TABLE on composite types. We want people to use ALTER
12764          * TYPE for that.
12765          */
12766         if (reltype != OBJECT_TYPE && relkind == RELKIND_COMPOSITE_TYPE)
12767                 ereport(ERROR,
12768                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12769                                  errmsg("\"%s\" is a composite type", rv->relname),
12770                                  errhint("Use ALTER TYPE instead.")));
12771
12772         /*
12773          * Don't allow ALTER TABLE .. SET SCHEMA on relations that can't be moved
12774          * to a different schema, such as indexes and TOAST tables.
12775          */
12776         if (IsA(stmt, AlterObjectSchemaStmt) &&
12777                 relkind != RELKIND_RELATION &&
12778                 relkind != RELKIND_VIEW &&
12779                 relkind != RELKIND_MATVIEW &&
12780                 relkind != RELKIND_SEQUENCE &&
12781                 relkind != RELKIND_FOREIGN_TABLE &&
12782                 relkind != RELKIND_PARTITIONED_TABLE)
12783                 ereport(ERROR,
12784                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12785                                  errmsg("\"%s\" is not a table, view, materialized view, sequence, or foreign table",
12786                                                 rv->relname)));
12787
12788         ReleaseSysCache(tuple);
12789 }
12790
12791 /*
12792  * Transform any expressions present in the partition key
12793  */
12794 static PartitionSpec *
12795 transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
12796 {
12797         PartitionSpec *newspec;
12798         ParseState *pstate;
12799         RangeTblEntry *rte;
12800         ListCell   *l;
12801
12802         newspec = makeNode(PartitionSpec);
12803
12804         newspec->strategy = partspec->strategy;
12805         newspec->location = partspec->location;
12806         newspec->partParams = NIL;
12807
12808         /* Parse partitioning strategy name */
12809         if (!pg_strcasecmp(partspec->strategy, "list"))
12810                 *strategy = PARTITION_STRATEGY_LIST;
12811         else if (!pg_strcasecmp(partspec->strategy, "range"))
12812                 *strategy = PARTITION_STRATEGY_RANGE;
12813         else
12814                 ereport(ERROR,
12815                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
12816                                  errmsg("unrecognized partitioning strategy \"%s\"",
12817                                                 partspec->strategy)));
12818
12819         /*
12820          * Create a dummy ParseState and insert the target relation as its sole
12821          * rangetable entry.  We need a ParseState for transformExpr.
12822          */
12823         pstate = make_parsestate(NULL);
12824         rte = addRangeTableEntryForRelation(pstate, rel, NULL, false, true);
12825         addRTEtoQuery(pstate, rte, true, true, true);
12826
12827         /* take care of any partition expressions */
12828         foreach(l, partspec->partParams)
12829         {
12830                 ListCell   *lc;
12831                 PartitionElem *pelem = (PartitionElem *) lfirst(l);
12832
12833                 /* Check for PARTITION BY ... (foo, foo) */
12834                 foreach(lc, newspec->partParams)
12835                 {
12836                         PartitionElem *pparam = (PartitionElem *) lfirst(lc);
12837
12838                         if (pelem->name && pparam->name &&
12839                                 !strcmp(pelem->name, pparam->name))
12840                                 ereport(ERROR,
12841                                                 (errcode(ERRCODE_DUPLICATE_COLUMN),
12842                                                  errmsg("column \"%s\" appears more than once in partition key",
12843                                                                 pelem->name),
12844                                                  parser_errposition(pstate, pelem->location)));
12845                 }
12846
12847                 if (pelem->expr)
12848                 {
12849                         /* Now do parse transformation of the expression */
12850                         pelem->expr = transformExpr(pstate, pelem->expr,
12851                                                                                 EXPR_KIND_PARTITION_EXPRESSION);
12852
12853                         /* we have to fix its collations too */
12854                         assign_expr_collations(pstate, pelem->expr);
12855                 }
12856
12857                 newspec->partParams = lappend(newspec->partParams, pelem);
12858         }
12859
12860         return newspec;
12861 }
12862
12863 /*
12864  * Compute per-partition-column information from a list of PartitionElem's
12865  */
12866 static void
12867 ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
12868                                           List **partexprs, Oid *partopclass, Oid *partcollation)
12869 {
12870         int                     attn;
12871         ListCell   *lc;
12872
12873         attn = 0;
12874         foreach(lc, partParams)
12875         {
12876                 PartitionElem *pelem = (PartitionElem *) lfirst(lc);
12877                 Oid                     atttype;
12878                 Oid                     attcollation;
12879
12880                 if (pelem->name != NULL)
12881                 {
12882                         /* Simple attribute reference */
12883                         HeapTuple       atttuple;
12884                         Form_pg_attribute attform;
12885
12886                         atttuple = SearchSysCacheAttName(RelationGetRelid(rel), pelem->name);
12887                         if (!HeapTupleIsValid(atttuple))
12888                                 ereport(ERROR,
12889                                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
12890                                 errmsg("column \"%s\" named in partition key does not exist",
12891                                            pelem->name)));
12892                         attform = (Form_pg_attribute) GETSTRUCT(atttuple);
12893
12894                         if (attform->attnum <= 0)
12895                                 ereport(ERROR,
12896                                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
12897                                    errmsg("cannot use system column \"%s\" in partition key",
12898                                                   pelem->name)));
12899
12900                         partattrs[attn] = attform->attnum;
12901                         atttype = attform->atttypid;
12902                         attcollation = attform->attcollation;
12903                         ReleaseSysCache(atttuple);
12904
12905                         /* Note that whole-row references can't happen here; see below */
12906                 }
12907                 else
12908                 {
12909                         /* Expression */
12910                         Node       *expr = pelem->expr;
12911
12912                         Assert(expr != NULL);
12913                         atttype = exprType(expr);
12914                         attcollation = exprCollation(expr);
12915
12916                         /*
12917                          * Strip any top-level COLLATE clause.  This ensures that we treat
12918                          * "x COLLATE y" and "(x COLLATE y)" alike.
12919                          */
12920                         while (IsA(expr, CollateExpr))
12921                                 expr = (Node *) ((CollateExpr *) expr)->arg;
12922
12923                         if (IsA(expr, Var) &&
12924                                 ((Var *) expr)->varattno != InvalidAttrNumber)
12925                         {
12926                                 /*
12927                                  * User wrote "(column)" or "(column COLLATE something)".
12928                                  * Treat it like simple attribute anyway.
12929                                  */
12930                                 partattrs[attn] = ((Var *) expr)->varattno;
12931                         }
12932                         else
12933                         {
12934                                 Bitmapset  *expr_attrs = NULL;
12935
12936                                 partattrs[attn] = 0;    /* marks the column as expression */
12937                                 *partexprs = lappend(*partexprs, expr);
12938
12939                                 /*
12940                                  * Note that expression_planner does not change the passed in
12941                                  * expression destructively and we have already saved the
12942                                  * expression to be stored into the catalog above.
12943                                  */
12944                                 expr = (Node *) expression_planner((Expr *) expr);
12945
12946                                 /*
12947                                  * Partition expression cannot contain mutable functions,
12948                                  * because a given row must always map to the same partition
12949                                  * as long as there is no change in the partition boundary
12950                                  * structure.
12951                                  */
12952                                 if (contain_mutable_functions(expr))
12953                                         ereport(ERROR,
12954                                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
12955                                                          errmsg("functions in partition key expression must be marked IMMUTABLE")));
12956
12957                                 /*
12958                                  * While it is not exactly *wrong* for an expression to be a
12959                                  * constant value, it seems better to prevent such input.
12960                                  */
12961                                 if (IsA(expr, Const))
12962                                         ereport(ERROR,
12963                                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
12964                                                          errmsg("cannot use constant expression as partition key")));
12965
12966                                 /*
12967                                  * transformPartitionSpec() should have already rejected
12968                                  * subqueries, aggregates, window functions, and SRFs, based
12969                                  * on the EXPR_KIND_ for partition expressions.
12970                                  */
12971
12972                                 /* Cannot have expressions containing whole-row references */
12973                                 pull_varattnos(expr, 1, &expr_attrs);
12974                                 if (bms_is_member(0 - FirstLowInvalidHeapAttributeNumber,
12975                                                                   expr_attrs))
12976                                         ereport(ERROR,
12977                                                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
12978                                                          errmsg("partition key expressions cannot contain whole-row references")));
12979                         }
12980                 }
12981
12982                 /*
12983                  * Apply collation override if any
12984                  */
12985                 if (pelem->collation)
12986                         attcollation = get_collation_oid(pelem->collation, false);
12987
12988                 /*
12989                  * Check we have a collation iff it's a collatable type.  The only
12990                  * expected failures here are (1) COLLATE applied to a noncollatable
12991                  * type, or (2) partition expression had an unresolved collation. But
12992                  * we might as well code this to be a complete consistency check.
12993                  */
12994                 if (type_is_collatable(atttype))
12995                 {
12996                         if (!OidIsValid(attcollation))
12997                                 ereport(ERROR,
12998                                                 (errcode(ERRCODE_INDETERMINATE_COLLATION),
12999                                                  errmsg("could not determine which collation to use for partition expression"),
13000                                                  errhint("Use the COLLATE clause to set the collation explicitly.")));
13001                 }
13002                 else
13003                 {
13004                         if (OidIsValid(attcollation))
13005                                 ereport(ERROR,
13006                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
13007                                                  errmsg("collations are not supported by type %s",
13008                                                                 format_type_be(atttype))));
13009                 }
13010
13011                 partcollation[attn] = attcollation;
13012
13013                 /*
13014                  * Identify a btree opclass to use. Currently, we use only btree
13015                  * operators, which seems enough for list and range partitioning.
13016                  */
13017                 if (!pelem->opclass)
13018                 {
13019                         partopclass[attn] = GetDefaultOpClass(atttype, BTREE_AM_OID);
13020
13021                         if (!OidIsValid(partopclass[attn]))
13022                                 ereport(ERROR,
13023                                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
13024                                    errmsg("data type %s has no default btree operator class",
13025                                                   format_type_be(atttype)),
13026                                                  errhint("You must specify a btree operator class or define a default btree operator class for the data type.")));
13027                 }
13028                 else
13029                         partopclass[attn] = ResolveOpClass(pelem->opclass,
13030                                                                                            atttype,
13031                                                                                            "btree",
13032                                                                                            BTREE_AM_OID);
13033
13034                 attn++;
13035         }
13036 }
13037
13038 /*
13039  * ALTER TABLE <name> ATTACH PARTITION <partition-name> FOR VALUES
13040  *
13041  * Return the address of the newly attached partition.
13042  */
13043 static ObjectAddress
13044 ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
13045 {
13046         PartitionKey key = RelationGetPartitionKey(rel);
13047         Relation        attachRel,
13048                                 catalog;
13049         List       *childrels;
13050         TupleConstr *attachRel_constr;
13051         List       *partConstraint,
13052                            *existConstraint;
13053         SysScanDesc scan;
13054         ScanKeyData skey;
13055         AttrNumber      attno;
13056         int                     natts;
13057         TupleDesc       tupleDesc;
13058         bool            skip_validate = false;
13059         ObjectAddress address;
13060
13061         attachRel = heap_openrv(cmd->name, AccessExclusiveLock);
13062
13063         /*
13064          * Must be owner of both parent and source table -- parent was checked by
13065          * ATSimplePermissions call in ATPrepCmd
13066          */
13067         ATSimplePermissions(attachRel, ATT_TABLE | ATT_FOREIGN_TABLE);
13068
13069         /* A partition can only have one parent */
13070         if (attachRel->rd_rel->relispartition)
13071                 ereport(ERROR,
13072                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
13073                                  errmsg("\"%s\" is already a partition",
13074                                                 RelationGetRelationName(attachRel))));
13075
13076         if (OidIsValid(attachRel->rd_rel->reloftype))
13077                 ereport(ERROR,
13078                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
13079                                  errmsg("cannot attach a typed table as partition")));
13080
13081         /*
13082          * Table being attached should not already be part of inheritance; either
13083          * as a child table...
13084          */
13085         catalog = heap_open(InheritsRelationId, AccessShareLock);
13086         ScanKeyInit(&skey,
13087                                 Anum_pg_inherits_inhrelid,
13088                                 BTEqualStrategyNumber, F_OIDEQ,
13089                                 ObjectIdGetDatum(RelationGetRelid(attachRel)));
13090         scan = systable_beginscan(catalog, InheritsRelidSeqnoIndexId, true,
13091                                                           NULL, 1, &skey);
13092         if (HeapTupleIsValid(systable_getnext(scan)))
13093                 ereport(ERROR,
13094                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
13095                                  errmsg("cannot attach inheritance child as partition")));
13096         systable_endscan(scan);
13097
13098         /* ...or as a parent table (except the case when it is partitioned) */
13099         ScanKeyInit(&skey,
13100                                 Anum_pg_inherits_inhparent,
13101                                 BTEqualStrategyNumber, F_OIDEQ,
13102                                 ObjectIdGetDatum(RelationGetRelid(attachRel)));
13103         scan = systable_beginscan(catalog, InheritsParentIndexId, true, NULL,
13104                                                           1, &skey);
13105         if (HeapTupleIsValid(systable_getnext(scan)) &&
13106                 attachRel->rd_rel->relkind == RELKIND_RELATION)
13107                 ereport(ERROR,
13108                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
13109                                  errmsg("cannot attach inheritance parent as partition")));
13110         systable_endscan(scan);
13111         heap_close(catalog, AccessShareLock);
13112
13113         /*
13114          * Prevent circularity by seeing if rel is a partition of attachRel. (In
13115          * particular, this disallows making a rel a partition of itself.)
13116          */
13117         childrels = find_all_inheritors(RelationGetRelid(attachRel),
13118                                                                         AccessShareLock, NULL);
13119         if (list_member_oid(childrels, RelationGetRelid(rel)))
13120                 ereport(ERROR,
13121                                 (errcode(ERRCODE_DUPLICATE_TABLE),
13122                                  errmsg("circular inheritance not allowed"),
13123                                  errdetail("\"%s\" is already a child of \"%s\".",
13124                                                    RelationGetRelationName(rel),
13125                                                    RelationGetRelationName(attachRel))));
13126
13127         /* Temp parent cannot have a partition that is itself not a temp */
13128         if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
13129                 attachRel->rd_rel->relpersistence != RELPERSISTENCE_TEMP)
13130                 ereport(ERROR,
13131                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
13132                                  errmsg("cannot attach a permanent relation as partition of temporary relation \"%s\"",
13133                                                 RelationGetRelationName(rel))));
13134
13135         /* If the parent is temp, it must belong to this session */
13136         if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
13137                 !rel->rd_islocaltemp)
13138                 ereport(ERROR,
13139                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
13140                                  errmsg("cannot attach as partition of temporary relation of another session")));
13141
13142         /* Ditto for the partition */
13143         if (attachRel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
13144                 !attachRel->rd_islocaltemp)
13145                 ereport(ERROR,
13146                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
13147                                  errmsg("cannot attach temporary relation of another session as partition")));
13148
13149         /* If parent has OIDs then child must have OIDs */
13150         if (rel->rd_rel->relhasoids && !attachRel->rd_rel->relhasoids)
13151                 ereport(ERROR,
13152                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
13153                          errmsg("cannot attach table \"%s\" without OIDs as partition of"
13154                            " table \"%s\" with OIDs", RelationGetRelationName(attachRel),
13155                                         RelationGetRelationName(rel))));
13156
13157         /* OTOH, if parent doesn't have them, do not allow in attachRel either */
13158         if (attachRel->rd_rel->relhasoids && !rel->rd_rel->relhasoids)
13159                 ereport(ERROR,
13160                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
13161                   errmsg("cannot attach table \"%s\" with OIDs as partition of table"
13162                                  " \"%s\" without OIDs", RelationGetRelationName(attachRel),
13163                                  RelationGetRelationName(rel))));
13164
13165         /* Check if there are any columns in attachRel that aren't in the parent */
13166         tupleDesc = RelationGetDescr(attachRel);
13167         natts = tupleDesc->natts;
13168         for (attno = 1; attno <= natts; attno++)
13169         {
13170                 Form_pg_attribute attribute = tupleDesc->attrs[attno - 1];
13171                 char       *attributeName = NameStr(attribute->attname);
13172
13173                 /* Ignore dropped */
13174                 if (attribute->attisdropped)
13175                         continue;
13176
13177                 /* Try to find the column in parent (matching on column name) */
13178                 if (!SearchSysCacheExists2(ATTNAME,
13179                                                                    ObjectIdGetDatum(RelationGetRelid(rel)),
13180                                                                    CStringGetDatum(attributeName)))
13181                         ereport(ERROR,
13182                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
13183                                          errmsg("table \"%s\" contains column \"%s\" not found in parent \"%s\"",
13184                                                         RelationGetRelationName(attachRel), attributeName,
13185                                                         RelationGetRelationName(rel)),
13186                                          errdetail("New partition should contain only the columns present in parent.")));
13187         }
13188
13189         /* OK to create inheritance.  Rest of the checks performed there */
13190         CreateInheritance(attachRel, rel);
13191
13192         /*
13193          * Check that the new partition's bound is valid and does not overlap any
13194          * of existing partitions of the parent - note that it does not return on
13195          * error.
13196          */
13197         check_new_partition_bound(RelationGetRelationName(attachRel), rel,
13198                                                           cmd->bound);
13199
13200         /* Update the pg_class entry. */
13201         StorePartitionBound(attachRel, rel, cmd->bound);
13202
13203         /*
13204          * Generate partition constraint from the partition bound specification.
13205          * If the parent itself is a partition, make sure to include its
13206          * constraint as well.
13207          */
13208         partConstraint = list_concat(get_qual_from_partbound(attachRel, rel,
13209                                                                                                                  cmd->bound),
13210                                                                  RelationGetPartitionQual(rel));
13211         partConstraint = (List *) eval_const_expressions(NULL,
13212                                                                                                          (Node *) partConstraint);
13213         partConstraint = (List *) canonicalize_qual((Expr *) partConstraint);
13214         partConstraint = list_make1(make_ands_explicit(partConstraint));
13215
13216         /*
13217          * Check if we can do away with having to scan the table being attached to
13218          * validate the partition constraint, by *proving* that the existing
13219          * constraints of the table *imply* the partition predicate.  We include
13220          * the table's check constraints and NOT NULL constraints in the list of
13221          * clauses passed to predicate_implied_by().
13222          *
13223          * There is a case in which we cannot rely on just the result of the
13224          * proof.
13225          */
13226         attachRel_constr = tupleDesc->constr;
13227         existConstraint = NIL;
13228         if (attachRel_constr != NULL)
13229         {
13230                 int                     num_check = attachRel_constr->num_check;
13231                 int                     i;
13232                 Bitmapset  *not_null_attrs = NULL;
13233                 List       *part_constr;
13234                 ListCell   *lc;
13235                 bool            partition_accepts_null = true;
13236                 int                     partnatts;
13237
13238                 if (attachRel_constr->has_not_null)
13239                 {
13240                         int                     natts = attachRel->rd_att->natts;
13241
13242                         for (i = 1; i <= natts; i++)
13243                         {
13244                                 Form_pg_attribute att = attachRel->rd_att->attrs[i - 1];
13245
13246                                 if (att->attnotnull && !att->attisdropped)
13247                                 {
13248                                         NullTest   *ntest = makeNode(NullTest);
13249
13250                                         ntest->arg = (Expr *) makeVar(1,
13251                                                                                                   i,
13252                                                                                                   att->atttypid,
13253                                                                                                   att->atttypmod,
13254                                                                                                   att->attcollation,
13255                                                                                                   0);
13256                                         ntest->nulltesttype = IS_NOT_NULL;
13257
13258                                         /*
13259                                          * argisrow=false is correct even for a composite column,
13260                                          * because attnotnull does not represent a SQL-spec IS NOT
13261                                          * NULL test in such a case, just IS DISTINCT FROM NULL.
13262                                          */
13263                                         ntest->argisrow = false;
13264                                         ntest->location = -1;
13265                                         existConstraint = lappend(existConstraint, ntest);
13266                                         not_null_attrs = bms_add_member(not_null_attrs, i);
13267                                 }
13268                         }
13269                 }
13270
13271                 for (i = 0; i < num_check; i++)
13272                 {
13273                         Node       *cexpr;
13274
13275                         /*
13276                          * If this constraint hasn't been fully validated yet, we must
13277                          * ignore it here.
13278                          */
13279                         if (!attachRel_constr->check[i].ccvalid)
13280                                 continue;
13281
13282                         cexpr = stringToNode(attachRel_constr->check[i].ccbin);
13283
13284                         /*
13285                          * Run each expression through const-simplification and
13286                          * canonicalization.  It is necessary, because we will be
13287                          * comparing it to similarly-processed qual clauses, and may fail
13288                          * to detect valid matches without this.
13289                          */
13290                         cexpr = eval_const_expressions(NULL, cexpr);
13291                         cexpr = (Node *) canonicalize_qual((Expr *) cexpr);
13292
13293                         existConstraint = list_concat(existConstraint,
13294                                                                                   make_ands_implicit((Expr *) cexpr));
13295                 }
13296
13297                 existConstraint = list_make1(make_ands_explicit(existConstraint));
13298
13299                 /* And away we go ... */
13300                 if (predicate_implied_by(partConstraint, existConstraint))
13301                         skip_validate = true;
13302
13303                 /*
13304                  * We choose to err on the safer side, i.e., give up on skipping the
13305                  * validation scan, if the partition key column doesn't have the NOT
13306                  * NULL constraint and the table is to become a list partition that
13307                  * does not accept nulls.  In this case, the partition predicate
13308                  * (partConstraint) does include an 'key IS NOT NULL' expression,
13309                  * however, because of the way predicate_implied_by_simple_clause() is
13310                  * designed to handle IS NOT NULL predicates in the absence of a IS
13311                  * NOT NULL clause, we cannot rely on just the above proof.
13312                  *
13313                  * That is not an issue in case of a range partition, because if there
13314                  * were no NOT NULL constraint defined on the key columns, an error
13315                  * would be thrown before we get here anyway.  That is not true,
13316                  * however, if any of the partition keys is an expression, which is
13317                  * handled below.
13318                  */
13319                 part_constr = linitial(partConstraint);
13320                 part_constr = make_ands_implicit((Expr *) part_constr);
13321
13322                 /*
13323                  * part_constr contains an IS NOT NULL expression, if this is a list
13324                  * partition that does not accept nulls (in fact, also if this is a
13325                  * range partition and some partition key is an expression, but we
13326                  * never skip validation in that case anyway; see below)
13327                  */
13328                 foreach(lc, part_constr)
13329                 {
13330                         Node       *expr = lfirst(lc);
13331
13332                         if (IsA(expr, NullTest) &&
13333                                 ((NullTest *) expr)->nulltesttype == IS_NOT_NULL)
13334                         {
13335                                 partition_accepts_null = false;
13336                                 break;
13337                         }
13338                 }
13339
13340                 partnatts = get_partition_natts(key);
13341                 for (i = 0; i < partnatts; i++)
13342                 {
13343                         AttrNumber      partattno;
13344
13345                         partattno = get_partition_col_attnum(key, i);
13346
13347                         /* If partition key is an expression, must not skip validation */
13348                         if (!partition_accepts_null &&
13349                                 (partattno == 0 ||
13350                                  !bms_is_member(partattno, not_null_attrs)))
13351                                 skip_validate = false;
13352                 }
13353         }
13354
13355         /* It's safe to skip the validation scan after all */
13356         if (skip_validate)
13357                 ereport(INFO,
13358                                 (errmsg("partition constraint for table \"%s\" is implied by existing constraints",
13359                                                 RelationGetRelationName(attachRel))));
13360
13361         /*
13362          * Set up to have the table to be scanned to validate the partition
13363          * constraint (see partConstraint above).  If it's a partitioned table, we
13364          * instead schdule its leaf partitions to be scanned instead.
13365          */
13366         if (!skip_validate)
13367         {
13368                 List       *all_parts;
13369                 ListCell   *lc;
13370
13371                 /* Take an exclusive lock on the partitions to be checked */
13372                 if (attachRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
13373                         all_parts = find_all_inheritors(RelationGetRelid(attachRel),
13374                                                                                         AccessExclusiveLock, NULL);
13375                 else
13376                         all_parts = list_make1_oid(RelationGetRelid(attachRel));
13377
13378                 foreach(lc, all_parts)
13379                 {
13380                         AlteredTableInfo *tab;
13381                         Oid                     part_relid = lfirst_oid(lc);
13382                         Relation        part_rel;
13383                         Expr       *constr;
13384                         List       *my_constr;
13385
13386                         /* Lock already taken */
13387                         if (part_relid != RelationGetRelid(attachRel))
13388                                 part_rel = heap_open(part_relid, NoLock);
13389                         else
13390                                 part_rel = attachRel;
13391
13392                         /*
13393                          * Skip if it's a partitioned table.  Only RELKIND_RELATION
13394                          * relations (ie, leaf partitions) need to be scanned.
13395                          */
13396                         if (part_rel != attachRel &&
13397                                 part_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
13398                         {
13399                                 heap_close(part_rel, NoLock);
13400                                 continue;
13401                         }
13402
13403                         /* Grab a work queue entry */
13404                         tab = ATGetQueueEntry(wqueue, part_rel);
13405
13406                         constr = linitial(partConstraint);
13407                         my_constr = make_ands_implicit((Expr *) constr);
13408                         tab->partition_constraint = map_partition_varattnos(my_constr,
13409                                                                                                                                 1,
13410                                                                                                                                 part_rel,
13411                                                                                                                                 rel);
13412                         /* keep our lock until commit */
13413                         if (part_rel != attachRel)
13414                                 heap_close(part_rel, NoLock);
13415                 }
13416         }
13417
13418         ObjectAddressSet(address, RelationRelationId, RelationGetRelid(attachRel));
13419
13420         /* keep our lock until commit */
13421         heap_close(attachRel, NoLock);
13422
13423         return address;
13424 }
13425
13426 /*
13427  * ALTER TABLE DETACH PARTITION
13428  *
13429  * Return the address of the relation that is no longer a partition of rel.
13430  */
13431 static ObjectAddress
13432 ATExecDetachPartition(Relation rel, RangeVar *name)
13433 {
13434         Relation        partRel,
13435                                 classRel;
13436         HeapTuple       tuple,
13437                                 newtuple;
13438         Datum           new_val[Natts_pg_class];
13439         bool            isnull,
13440                                 new_null[Natts_pg_class],
13441                                 new_repl[Natts_pg_class];
13442         ObjectAddress address;
13443
13444         partRel = heap_openrv(name, AccessShareLock);
13445
13446         /* All inheritance related checks are performed within the function */
13447         RemoveInheritance(partRel, rel);
13448
13449         /* Update pg_class tuple */
13450         classRel = heap_open(RelationRelationId, RowExclusiveLock);
13451         tuple = SearchSysCacheCopy1(RELOID,
13452                                                                 ObjectIdGetDatum(RelationGetRelid(partRel)));
13453         Assert(((Form_pg_class) GETSTRUCT(tuple))->relispartition);
13454
13455         (void) SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relpartbound,
13456                                                    &isnull);
13457         Assert(!isnull);
13458
13459         /* Clear relpartbound and reset relispartition */
13460         memset(new_val, 0, sizeof(new_val));
13461         memset(new_null, false, sizeof(new_null));
13462         memset(new_repl, false, sizeof(new_repl));
13463         new_val[Anum_pg_class_relpartbound - 1] = (Datum) 0;
13464         new_null[Anum_pg_class_relpartbound - 1] = true;
13465         new_repl[Anum_pg_class_relpartbound - 1] = true;
13466         newtuple = heap_modify_tuple(tuple, RelationGetDescr(classRel),
13467                                                                  new_val, new_null, new_repl);
13468
13469         ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = false;
13470         CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple);
13471         heap_freetuple(newtuple);
13472         heap_close(classRel, RowExclusiveLock);
13473
13474         /*
13475          * Invalidate the parent's relcache so that the partition is no longer
13476          * included in its partition descriptor.
13477          */
13478         CacheInvalidateRelcache(rel);
13479
13480         ObjectAddressSet(address, RelationRelationId, RelationGetRelid(partRel));
13481
13482         /* keep our lock until commit */
13483         heap_close(partRel, NoLock);
13484
13485         return address;
13486 }