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