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