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