]> granicus.if.org Git - postgresql/blob - src/backend/commands/tablecmds.c
Add two missing cases to ATWrongRelkindError.
[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_FOREIGN_TABLE:
4340                         msg = _("\"%s\" is not a table, view or foreign table");
4341                         break;
4342                 case ATT_TABLE | ATT_VIEW | ATT_MATVIEW | ATT_INDEX:
4343                         msg = _("\"%s\" is not a table, view, materialized view, or index");
4344                         break;
4345                 case ATT_TABLE | ATT_MATVIEW:
4346                         msg = _("\"%s\" is not a table or materialized view");
4347                         break;
4348                 case ATT_TABLE | ATT_MATVIEW | ATT_INDEX:
4349                         msg = _("\"%s\" is not a table, materialized view, or index");
4350                         break;
4351                 case ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE:
4352                         msg = _("\"%s\" is not a table, materialized view, or foreign table");
4353                         break;
4354                 case ATT_TABLE | ATT_FOREIGN_TABLE:
4355                         msg = _("\"%s\" is not a table or foreign table");
4356                         break;
4357                 case ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE:
4358                         msg = _("\"%s\" is not a table, composite type, or foreign table");
4359                         break;
4360                 case ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_FOREIGN_TABLE:
4361                         msg = _("\"%s\" is not a table, materialized view, composite type, or foreign table");
4362                         break;
4363                 case ATT_VIEW:
4364                         msg = _("\"%s\" is not a view");
4365                         break;
4366                 case ATT_FOREIGN_TABLE:
4367                         msg = _("\"%s\" is not a foreign table");
4368                         break;
4369                 default:
4370                         /* shouldn't get here, add all necessary cases above */
4371                         msg = _("\"%s\" is of the wrong type");
4372                         break;
4373         }
4374
4375         ereport(ERROR,
4376                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4377                          errmsg(msg, RelationGetRelationName(rel))));
4378 }
4379
4380 /*
4381  * ATSimpleRecursion
4382  *
4383  * Simple table recursion sufficient for most ALTER TABLE operations.
4384  * All direct and indirect children are processed in an unspecified order.
4385  * Note that if a child inherits from the original table via multiple
4386  * inheritance paths, it will be visited just once.
4387  */
4388 static void
4389 ATSimpleRecursion(List **wqueue, Relation rel,
4390                                   AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode)
4391 {
4392         /*
4393          * Propagate to children if desired.  Only plain tables and foreign tables
4394          * have children, so no need to search for other relkinds.
4395          */
4396         if (recurse &&
4397                 (rel->rd_rel->relkind == RELKIND_RELATION ||
4398                  rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE))
4399         {
4400                 Oid                     relid = RelationGetRelid(rel);
4401                 ListCell   *child;
4402                 List       *children;
4403
4404                 children = find_all_inheritors(relid, lockmode, NULL);
4405
4406                 /*
4407                  * find_all_inheritors does the recursive search of the inheritance
4408                  * hierarchy, so all we have to do is process all of the relids in the
4409                  * list that it returns.
4410                  */
4411                 foreach(child, children)
4412                 {
4413                         Oid                     childrelid = lfirst_oid(child);
4414                         Relation        childrel;
4415
4416                         if (childrelid == relid)
4417                                 continue;
4418                         /* find_all_inheritors already got lock */
4419                         childrel = relation_open(childrelid, NoLock);
4420                         CheckTableNotInUse(childrel, "ALTER TABLE");
4421                         ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode);
4422                         relation_close(childrel, NoLock);
4423                 }
4424         }
4425 }
4426
4427 /*
4428  * ATTypedTableRecursion
4429  *
4430  * Propagate ALTER TYPE operations to the typed tables of that type.
4431  * Also check the RESTRICT/CASCADE behavior.  Given CASCADE, also permit
4432  * recursion to inheritance children of the typed tables.
4433  */
4434 static void
4435 ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
4436                                           LOCKMODE lockmode)
4437 {
4438         ListCell   *child;
4439         List       *children;
4440
4441         Assert(rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
4442
4443         children = find_typed_table_dependencies(rel->rd_rel->reltype,
4444                                                                                          RelationGetRelationName(rel),
4445                                                                                          cmd->behavior);
4446
4447         foreach(child, children)
4448         {
4449                 Oid                     childrelid = lfirst_oid(child);
4450                 Relation        childrel;
4451
4452                 childrel = relation_open(childrelid, lockmode);
4453                 CheckTableNotInUse(childrel, "ALTER TABLE");
4454                 ATPrepCmd(wqueue, childrel, cmd, true, true, lockmode);
4455                 relation_close(childrel, NoLock);
4456         }
4457 }
4458
4459
4460 /*
4461  * find_composite_type_dependencies
4462  *
4463  * Check to see if a composite type is being used as a column in some
4464  * other table (possibly nested several levels deep in composite types!).
4465  * Eventually, we'd like to propagate the check or rewrite operation
4466  * into other such tables, but for now, just error out if we find any.
4467  *
4468  * Caller should provide either a table name or a type name (not both) to
4469  * report in the error message, if any.
4470  *
4471  * We assume that functions and views depending on the type are not reasons
4472  * to reject the ALTER.  (How safe is this really?)
4473  */
4474 void
4475 find_composite_type_dependencies(Oid typeOid, Relation origRelation,
4476                                                                  const char *origTypeName)
4477 {
4478         Relation        depRel;
4479         ScanKeyData key[2];
4480         SysScanDesc depScan;
4481         HeapTuple       depTup;
4482         Oid                     arrayOid;
4483
4484         /*
4485          * We scan pg_depend to find those things that depend on the rowtype. (We
4486          * assume we can ignore refobjsubid for a rowtype.)
4487          */
4488         depRel = heap_open(DependRelationId, AccessShareLock);
4489
4490         ScanKeyInit(&key[0],
4491                                 Anum_pg_depend_refclassid,
4492                                 BTEqualStrategyNumber, F_OIDEQ,
4493                                 ObjectIdGetDatum(TypeRelationId));
4494         ScanKeyInit(&key[1],
4495                                 Anum_pg_depend_refobjid,
4496                                 BTEqualStrategyNumber, F_OIDEQ,
4497                                 ObjectIdGetDatum(typeOid));
4498
4499         depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
4500                                                                  NULL, 2, key);
4501
4502         while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
4503         {
4504                 Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
4505                 Relation        rel;
4506                 Form_pg_attribute att;
4507
4508                 /* Ignore dependees that aren't user columns of relations */
4509                 /* (we assume system columns are never of rowtypes) */
4510                 if (pg_depend->classid != RelationRelationId ||
4511                         pg_depend->objsubid <= 0)
4512                         continue;
4513
4514                 rel = relation_open(pg_depend->objid, AccessShareLock);
4515                 att = rel->rd_att->attrs[pg_depend->objsubid - 1];
4516
4517                 if (rel->rd_rel->relkind == RELKIND_RELATION ||
4518                         rel->rd_rel->relkind == RELKIND_MATVIEW)
4519                 {
4520                         if (origTypeName)
4521                                 ereport(ERROR,
4522                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4523                                                  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4524                                                                 origTypeName,
4525                                                                 RelationGetRelationName(rel),
4526                                                                 NameStr(att->attname))));
4527                         else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
4528                                 ereport(ERROR,
4529                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4530                                                  errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
4531                                                                 RelationGetRelationName(origRelation),
4532                                                                 RelationGetRelationName(rel),
4533                                                                 NameStr(att->attname))));
4534                         else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4535                                 ereport(ERROR,
4536                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4537                                                  errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
4538                                                                 RelationGetRelationName(origRelation),
4539                                                                 RelationGetRelationName(rel),
4540                                                                 NameStr(att->attname))));
4541                         else
4542                                 ereport(ERROR,
4543                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4544                                                  errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
4545                                                                 RelationGetRelationName(origRelation),
4546                                                                 RelationGetRelationName(rel),
4547                                                                 NameStr(att->attname))));
4548                 }
4549                 else if (OidIsValid(rel->rd_rel->reltype))
4550                 {
4551                         /*
4552                          * A view or composite type itself isn't a problem, but we must
4553                          * recursively check for indirect dependencies via its rowtype.
4554                          */
4555                         find_composite_type_dependencies(rel->rd_rel->reltype,
4556                                                                                          origRelation, origTypeName);
4557                 }
4558
4559                 relation_close(rel, AccessShareLock);
4560         }
4561
4562         systable_endscan(depScan);
4563
4564         relation_close(depRel, AccessShareLock);
4565
4566         /*
4567          * If there's an array type for the rowtype, must check for uses of it,
4568          * too.
4569          */
4570         arrayOid = get_array_type(typeOid);
4571         if (OidIsValid(arrayOid))
4572                 find_composite_type_dependencies(arrayOid, origRelation, origTypeName);
4573 }
4574
4575
4576 /*
4577  * find_typed_table_dependencies
4578  *
4579  * Check to see if a composite type is being used as the type of a
4580  * typed table.  Abort if any are found and behavior is RESTRICT.
4581  * Else return the list of tables.
4582  */
4583 static List *
4584 find_typed_table_dependencies(Oid typeOid, const char *typeName, DropBehavior behavior)
4585 {
4586         Relation        classRel;
4587         ScanKeyData key[1];
4588         HeapScanDesc scan;
4589         HeapTuple       tuple;
4590         List       *result = NIL;
4591
4592         classRel = heap_open(RelationRelationId, AccessShareLock);
4593
4594         ScanKeyInit(&key[0],
4595                                 Anum_pg_class_reloftype,
4596                                 BTEqualStrategyNumber, F_OIDEQ,
4597                                 ObjectIdGetDatum(typeOid));
4598
4599         scan = heap_beginscan_catalog(classRel, 1, key);
4600
4601         while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
4602         {
4603                 if (behavior == DROP_RESTRICT)
4604                         ereport(ERROR,
4605                                         (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
4606                                          errmsg("cannot alter type \"%s\" because it is the type of a typed table",
4607                                                         typeName),
4608                         errhint("Use ALTER ... CASCADE to alter the typed tables too.")));
4609                 else
4610                         result = lappend_oid(result, HeapTupleGetOid(tuple));
4611         }
4612
4613         heap_endscan(scan);
4614         heap_close(classRel, AccessShareLock);
4615
4616         return result;
4617 }
4618
4619
4620 /*
4621  * check_of_type
4622  *
4623  * Check whether a type is suitable for CREATE TABLE OF/ALTER TABLE OF.  If it
4624  * isn't suitable, throw an error.  Currently, we require that the type
4625  * originated with CREATE TYPE AS.  We could support any row type, but doing so
4626  * would require handling a number of extra corner cases in the DDL commands.
4627  */
4628 void
4629 check_of_type(HeapTuple typetuple)
4630 {
4631         Form_pg_type typ = (Form_pg_type) GETSTRUCT(typetuple);
4632         bool            typeOk = false;
4633
4634         if (typ->typtype == TYPTYPE_COMPOSITE)
4635         {
4636                 Relation        typeRelation;
4637
4638                 Assert(OidIsValid(typ->typrelid));
4639                 typeRelation = relation_open(typ->typrelid, AccessShareLock);
4640                 typeOk = (typeRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
4641
4642                 /*
4643                  * Close the parent rel, but keep our AccessShareLock on it until xact
4644                  * commit.  That will prevent someone else from deleting or ALTERing
4645                  * the type before the typed table creation/conversion commits.
4646                  */
4647                 relation_close(typeRelation, NoLock);
4648         }
4649         if (!typeOk)
4650                 ereport(ERROR,
4651                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4652                                  errmsg("type %s is not a composite type",
4653                                                 format_type_be(HeapTupleGetOid(typetuple)))));
4654 }
4655
4656
4657 /*
4658  * ALTER TABLE ADD COLUMN
4659  *
4660  * Adds an additional attribute to a relation making the assumption that
4661  * CHECK, NOT NULL, and FOREIGN KEY constraints will be removed from the
4662  * AT_AddColumn AlterTableCmd by parse_utilcmd.c and added as independent
4663  * AlterTableCmd's.
4664  *
4665  * ADD COLUMN cannot use the normal ALTER TABLE recursion mechanism, because we
4666  * have to decide at runtime whether to recurse or not depending on whether we
4667  * actually add a column or merely merge with an existing column.  (We can't
4668  * check this in a static pre-pass because it won't handle multiple inheritance
4669  * situations correctly.)
4670  */
4671 static void
4672 ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
4673                                 bool is_view, AlterTableCmd *cmd, LOCKMODE lockmode)
4674 {
4675         if (rel->rd_rel->reloftype && !recursing)
4676                 ereport(ERROR,
4677                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4678                                  errmsg("cannot add column to typed table")));
4679
4680         if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
4681                 ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
4682
4683         if (recurse && !is_view)
4684                 cmd->subtype = AT_AddColumnRecurse;
4685 }
4686
4687 /*
4688  * Add a column to a table; this handles the AT_AddOids cases as well.  The
4689  * return value is the address of the new column in the parent relation.
4690  */
4691 static ObjectAddress
4692 ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
4693                                 ColumnDef *colDef, bool isOid,
4694                                 bool recurse, bool recursing, bool if_not_exists, LOCKMODE lockmode)
4695 {
4696         Oid                     myrelid = RelationGetRelid(rel);
4697         Relation        pgclass,
4698                                 attrdesc;
4699         HeapTuple       reltup;
4700         FormData_pg_attribute attribute;
4701         int                     newattnum;
4702         char            relkind;
4703         HeapTuple       typeTuple;
4704         Oid                     typeOid;
4705         int32           typmod;
4706         Oid                     collOid;
4707         Form_pg_type tform;
4708         Expr       *defval;
4709         List       *children;
4710         ListCell   *child;
4711         AclResult       aclresult;
4712         ObjectAddress address;
4713
4714         /* At top level, permission check was done in ATPrepCmd, else do it */
4715         if (recursing)
4716                 ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
4717
4718         attrdesc = heap_open(AttributeRelationId, RowExclusiveLock);
4719
4720         /*
4721          * Are we adding the column to a recursion child?  If so, check whether to
4722          * merge with an existing definition for the column.  If we do merge, we
4723          * must not recurse.  Children will already have the column, and recursing
4724          * into them would mess up attinhcount.
4725          */
4726         if (colDef->inhcount > 0)
4727         {
4728                 HeapTuple       tuple;
4729
4730                 /* Does child already have a column by this name? */
4731                 tuple = SearchSysCacheCopyAttName(myrelid, colDef->colname);
4732                 if (HeapTupleIsValid(tuple))
4733                 {
4734                         Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
4735                         Oid                     ctypeId;
4736                         int32           ctypmod;
4737                         Oid                     ccollid;
4738
4739                         /* Child column must match on type, typmod, and collation */
4740                         typenameTypeIdAndMod(NULL, colDef->typeName, &ctypeId, &ctypmod);
4741                         if (ctypeId != childatt->atttypid ||
4742                                 ctypmod != childatt->atttypmod)
4743                                 ereport(ERROR,
4744                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
4745                                                  errmsg("child table \"%s\" has different type for column \"%s\"",
4746                                                         RelationGetRelationName(rel), colDef->colname)));
4747                         ccollid = GetColumnDefCollation(NULL, colDef, ctypeId);
4748                         if (ccollid != childatt->attcollation)
4749                                 ereport(ERROR,
4750                                                 (errcode(ERRCODE_COLLATION_MISMATCH),
4751                                                  errmsg("child table \"%s\" has different collation for column \"%s\"",
4752                                                           RelationGetRelationName(rel), colDef->colname),
4753                                                  errdetail("\"%s\" versus \"%s\"",
4754                                                                    get_collation_name(ccollid),
4755                                                            get_collation_name(childatt->attcollation))));
4756
4757                         /* If it's OID, child column must actually be OID */
4758                         if (isOid && childatt->attnum != ObjectIdAttributeNumber)
4759                                 ereport(ERROR,
4760                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
4761                                  errmsg("child table \"%s\" has a conflicting \"%s\" column",
4762                                                 RelationGetRelationName(rel), colDef->colname)));
4763
4764                         /* Bump the existing child att's inhcount */
4765                         childatt->attinhcount++;
4766                         simple_heap_update(attrdesc, &tuple->t_self, tuple);
4767                         CatalogUpdateIndexes(attrdesc, tuple);
4768
4769                         heap_freetuple(tuple);
4770
4771                         /* Inform the user about the merge */
4772                         ereport(NOTICE,
4773                           (errmsg("merging definition of column \"%s\" for child \"%s\"",
4774                                           colDef->colname, RelationGetRelationName(rel))));
4775
4776                         heap_close(attrdesc, RowExclusiveLock);
4777                         return InvalidObjectAddress;
4778                 }
4779         }
4780
4781         pgclass = heap_open(RelationRelationId, RowExclusiveLock);
4782
4783         reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
4784         if (!HeapTupleIsValid(reltup))
4785                 elog(ERROR, "cache lookup failed for relation %u", myrelid);
4786         relkind = ((Form_pg_class) GETSTRUCT(reltup))->relkind;
4787
4788         /* skip if the name already exists and if_not_exists is true */
4789         if (!check_for_column_name_collision(rel, colDef->colname, if_not_exists))
4790         {
4791                 heap_close(attrdesc, RowExclusiveLock);
4792                 heap_freetuple(reltup);
4793                 heap_close(pgclass, RowExclusiveLock);
4794                 return InvalidObjectAddress;
4795         }
4796
4797         /* Determine the new attribute's number */
4798         if (isOid)
4799                 newattnum = ObjectIdAttributeNumber;
4800         else
4801         {
4802                 newattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts + 1;
4803                 if (newattnum > MaxHeapAttributeNumber)
4804                         ereport(ERROR,
4805                                         (errcode(ERRCODE_TOO_MANY_COLUMNS),
4806                                          errmsg("tables can have at most %d columns",
4807                                                         MaxHeapAttributeNumber)));
4808         }
4809
4810         typeTuple = typenameType(NULL, colDef->typeName, &typmod);
4811         tform = (Form_pg_type) GETSTRUCT(typeTuple);
4812         typeOid = HeapTupleGetOid(typeTuple);
4813
4814         aclresult = pg_type_aclcheck(typeOid, GetUserId(), ACL_USAGE);
4815         if (aclresult != ACLCHECK_OK)
4816                 aclcheck_error_type(aclresult, typeOid);
4817
4818         collOid = GetColumnDefCollation(NULL, colDef, typeOid);
4819
4820         /* make sure datatype is legal for a column */
4821         CheckAttributeType(colDef->colname, typeOid, collOid,
4822                                            list_make1_oid(rel->rd_rel->reltype),
4823                                            false);
4824
4825         /* construct new attribute's pg_attribute entry */
4826         attribute.attrelid = myrelid;
4827         namestrcpy(&(attribute.attname), colDef->colname);
4828         attribute.atttypid = typeOid;
4829         attribute.attstattarget = (newattnum > 0) ? -1 : 0;
4830         attribute.attlen = tform->typlen;
4831         attribute.attcacheoff = -1;
4832         attribute.atttypmod = typmod;
4833         attribute.attnum = newattnum;
4834         attribute.attbyval = tform->typbyval;
4835         attribute.attndims = list_length(colDef->typeName->arrayBounds);
4836         attribute.attstorage = tform->typstorage;
4837         attribute.attalign = tform->typalign;
4838         attribute.attnotnull = colDef->is_not_null;
4839         attribute.atthasdef = false;
4840         attribute.attisdropped = false;
4841         attribute.attislocal = colDef->is_local;
4842         attribute.attinhcount = colDef->inhcount;
4843         attribute.attcollation = collOid;
4844         /* attribute.attacl is handled by InsertPgAttributeTuple */
4845
4846         ReleaseSysCache(typeTuple);
4847
4848         InsertPgAttributeTuple(attrdesc, &attribute, NULL);
4849
4850         heap_close(attrdesc, RowExclusiveLock);
4851
4852         /*
4853          * Update pg_class tuple as appropriate
4854          */
4855         if (isOid)
4856                 ((Form_pg_class) GETSTRUCT(reltup))->relhasoids = true;
4857         else
4858                 ((Form_pg_class) GETSTRUCT(reltup))->relnatts = newattnum;
4859
4860         simple_heap_update(pgclass, &reltup->t_self, reltup);
4861
4862         /* keep catalog indexes current */
4863         CatalogUpdateIndexes(pgclass, reltup);
4864
4865         heap_freetuple(reltup);
4866
4867         /* Post creation hook for new attribute */
4868         InvokeObjectPostCreateHook(RelationRelationId, myrelid, newattnum);
4869
4870         heap_close(pgclass, RowExclusiveLock);
4871
4872         /* Make the attribute's catalog entry visible */
4873         CommandCounterIncrement();
4874
4875         /*
4876          * Store the DEFAULT, if any, in the catalogs
4877          */
4878         if (colDef->raw_default)
4879         {
4880                 RawColumnDefault *rawEnt;
4881
4882                 rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
4883                 rawEnt->attnum = attribute.attnum;
4884                 rawEnt->raw_default = copyObject(colDef->raw_default);
4885
4886                 /*
4887                  * This function is intended for CREATE TABLE, so it processes a
4888                  * _list_ of defaults, but we just do one.
4889                  */
4890                 AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
4891                                                                   false, true, false);
4892
4893                 /* Make the additional catalog changes visible */
4894                 CommandCounterIncrement();
4895         }
4896
4897         /*
4898          * Tell Phase 3 to fill in the default expression, if there is one.
4899          *
4900          * If there is no default, Phase 3 doesn't have to do anything, because
4901          * that effectively means that the default is NULL.  The heap tuple access
4902          * routines always check for attnum > # of attributes in tuple, and return
4903          * NULL if so, so without any modification of the tuple data we will get
4904          * the effect of NULL values in the new column.
4905          *
4906          * An exception occurs when the new column is of a domain type: the domain
4907          * might have a NOT NULL constraint, or a check constraint that indirectly
4908          * rejects nulls.  If there are any domain constraints then we construct
4909          * an explicit NULL default value that will be passed through
4910          * CoerceToDomain processing.  (This is a tad inefficient, since it causes
4911          * rewriting the table which we really don't have to do, but the present
4912          * design of domain processing doesn't offer any simple way of checking
4913          * the constraints more directly.)
4914          *
4915          * Note: we use build_column_default, and not just the cooked default
4916          * returned by AddRelationNewConstraints, so that the right thing happens
4917          * when a datatype's default applies.
4918          *
4919          * We skip this step completely for views and foreign tables.  For a view,
4920          * we can only get here from CREATE OR REPLACE VIEW, which historically
4921          * doesn't set up defaults, not even for domain-typed columns.  And in any
4922          * case we mustn't invoke Phase 3 on a view or foreign table, since they
4923          * have no storage.
4924          */
4925         if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE
4926                 && relkind != RELKIND_FOREIGN_TABLE && attribute.attnum > 0)
4927         {
4928                 defval = (Expr *) build_column_default(rel, attribute.attnum);
4929
4930                 if (!defval && DomainHasConstraints(typeOid))
4931                 {
4932                         Oid                     baseTypeId;
4933                         int32           baseTypeMod;
4934                         Oid                     baseTypeColl;
4935
4936                         baseTypeMod = typmod;
4937                         baseTypeId = getBaseTypeAndTypmod(typeOid, &baseTypeMod);
4938                         baseTypeColl = get_typcollation(baseTypeId);
4939                         defval = (Expr *) makeNullConst(baseTypeId, baseTypeMod, baseTypeColl);
4940                         defval = (Expr *) coerce_to_target_type(NULL,
4941                                                                                                         (Node *) defval,
4942                                                                                                         baseTypeId,
4943                                                                                                         typeOid,
4944                                                                                                         typmod,
4945                                                                                                         COERCION_ASSIGNMENT,
4946                                                                                                         COERCE_IMPLICIT_CAST,
4947                                                                                                         -1);
4948                         if (defval == NULL) /* should not happen */
4949                                 elog(ERROR, "failed to coerce base type to domain");
4950                 }
4951
4952                 if (defval)
4953                 {
4954                         NewColumnValue *newval;
4955
4956                         newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
4957                         newval->attnum = attribute.attnum;
4958                         newval->expr = expression_planner(defval);
4959
4960                         tab->newvals = lappend(tab->newvals, newval);
4961                         tab->rewrite |= AT_REWRITE_DEFAULT_VAL;
4962                 }
4963
4964                 /*
4965                  * If the new column is NOT NULL, tell Phase 3 it needs to test that.
4966                  * (Note we don't do this for an OID column.  OID will be marked not
4967                  * null, but since it's filled specially, there's no need to test
4968                  * anything.)
4969                  */
4970                 tab->new_notnull |= colDef->is_not_null;
4971         }
4972
4973         /*
4974          * If we are adding an OID column, we have to tell Phase 3 to rewrite the
4975          * table to fix that.
4976          */
4977         if (isOid)
4978                 tab->rewrite |= AT_REWRITE_ALTER_OID;
4979
4980         /*
4981          * Add needed dependency entries for the new column.
4982          */
4983         add_column_datatype_dependency(myrelid, newattnum, attribute.atttypid);
4984         add_column_collation_dependency(myrelid, newattnum, attribute.attcollation);
4985
4986         /*
4987          * Propagate to children as appropriate.  Unlike most other ALTER
4988          * routines, we have to do this one level of recursion at a time; we can't
4989          * use find_all_inheritors to do it in one pass.
4990          */
4991         children = find_inheritance_children(RelationGetRelid(rel), lockmode);
4992
4993         /*
4994          * If we are told not to recurse, there had better not be any child
4995          * tables; else the addition would put them out of step.
4996          */
4997         if (children && !recurse)
4998                 ereport(ERROR,
4999                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5000                                  errmsg("column must be added to child tables too")));
5001
5002         /* Children should see column as singly inherited */
5003         if (!recursing)
5004         {
5005                 colDef = copyObject(colDef);
5006                 colDef->inhcount = 1;
5007                 colDef->is_local = false;
5008         }
5009
5010         foreach(child, children)
5011         {
5012                 Oid                     childrelid = lfirst_oid(child);
5013                 Relation        childrel;
5014                 AlteredTableInfo *childtab;
5015
5016                 /* find_inheritance_children already got lock */
5017                 childrel = heap_open(childrelid, NoLock);
5018                 CheckTableNotInUse(childrel, "ALTER TABLE");
5019
5020                 /* Find or create work queue entry for this table */
5021                 childtab = ATGetQueueEntry(wqueue, childrel);
5022
5023                 /* Recurse to child; return value is ignored */
5024                 ATExecAddColumn(wqueue, childtab, childrel,
5025                                                 colDef, isOid, recurse, true,
5026                                                 if_not_exists, lockmode);
5027
5028                 heap_close(childrel, NoLock);
5029         }
5030
5031         ObjectAddressSubSet(address, RelationRelationId, myrelid, newattnum);
5032         return address;
5033 }
5034
5035 /*
5036  * If a new or renamed column will collide with the name of an existing
5037  * column and if_not_exists is false then error out, else do nothing.
5038  */
5039 static bool
5040 check_for_column_name_collision(Relation rel, const char *colname,
5041                                                                 bool if_not_exists)
5042 {
5043         HeapTuple       attTuple;
5044         int                     attnum;
5045
5046         /*
5047          * this test is deliberately not attisdropped-aware, since if one tries to
5048          * add a column matching a dropped column name, it's gonna fail anyway.
5049          */
5050         attTuple = SearchSysCache2(ATTNAME,
5051                                                            ObjectIdGetDatum(RelationGetRelid(rel)),
5052                                                            PointerGetDatum(colname));
5053         if (!HeapTupleIsValid(attTuple))
5054                 return true;
5055
5056         attnum = ((Form_pg_attribute) GETSTRUCT(attTuple))->attnum;
5057         ReleaseSysCache(attTuple);
5058
5059         /*
5060          * We throw a different error message for conflicts with system column
5061          * names, since they are normally not shown and the user might otherwise
5062          * be confused about the reason for the conflict.
5063          */
5064         if (attnum <= 0)
5065                 ereport(ERROR,
5066                                 (errcode(ERRCODE_DUPLICATE_COLUMN),
5067                          errmsg("column name \"%s\" conflicts with a system column name",
5068                                         colname)));
5069         else
5070         {
5071                 if (if_not_exists)
5072                 {
5073                         ereport(NOTICE,
5074                                         (errcode(ERRCODE_DUPLICATE_COLUMN),
5075                                          errmsg("column \"%s\" of relation \"%s\" already exists, skipping",
5076                                                         colname, RelationGetRelationName(rel))));
5077                         return false;
5078                 }
5079
5080                 ereport(ERROR,
5081                                 (errcode(ERRCODE_DUPLICATE_COLUMN),
5082                                  errmsg("column \"%s\" of relation \"%s\" already exists",
5083                                                 colname, RelationGetRelationName(rel))));
5084         }
5085
5086         return true;
5087 }
5088
5089 /*
5090  * Install a column's dependency on its datatype.
5091  */
5092 static void
5093 add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid)
5094 {
5095         ObjectAddress myself,
5096                                 referenced;
5097
5098         myself.classId = RelationRelationId;
5099         myself.objectId = relid;
5100         myself.objectSubId = attnum;
5101         referenced.classId = TypeRelationId;
5102         referenced.objectId = typid;
5103         referenced.objectSubId = 0;
5104         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
5105 }
5106
5107 /*
5108  * Install a column's dependency on its collation.
5109  */
5110 static void
5111 add_column_collation_dependency(Oid relid, int32 attnum, Oid collid)
5112 {
5113         ObjectAddress myself,
5114                                 referenced;
5115
5116         /* We know the default collation is pinned, so don't bother recording it */
5117         if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
5118         {
5119                 myself.classId = RelationRelationId;
5120                 myself.objectId = relid;
5121                 myself.objectSubId = attnum;
5122                 referenced.classId = CollationRelationId;
5123                 referenced.objectId = collid;
5124                 referenced.objectSubId = 0;
5125                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
5126         }
5127 }
5128
5129 /*
5130  * ALTER TABLE SET WITH OIDS
5131  *
5132  * Basically this is an ADD COLUMN for the special OID column.  We have
5133  * to cons up a ColumnDef node because the ADD COLUMN code needs one.
5134  */
5135 static void
5136 ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOCKMODE lockmode)
5137 {
5138         /* If we're recursing to a child table, the ColumnDef is already set up */
5139         if (cmd->def == NULL)
5140         {
5141                 ColumnDef  *cdef = makeNode(ColumnDef);
5142
5143                 cdef->colname = pstrdup("oid");
5144                 cdef->typeName = makeTypeNameFromOid(OIDOID, -1);
5145                 cdef->inhcount = 0;
5146                 cdef->is_local = true;
5147                 cdef->is_not_null = true;
5148                 cdef->storage = 0;
5149                 cdef->location = -1;
5150                 cmd->def = (Node *) cdef;
5151         }
5152         ATPrepAddColumn(wqueue, rel, recurse, false, false, cmd, lockmode);
5153
5154         if (recurse)
5155                 cmd->subtype = AT_AddOidsRecurse;
5156 }
5157
5158 /*
5159  * ALTER TABLE ALTER COLUMN DROP NOT NULL
5160  *
5161  * Return the address of the modified column.  If the column was already
5162  * nullable, InvalidObjectAddress is returned.
5163  */
5164 static ObjectAddress
5165 ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
5166 {
5167         HeapTuple       tuple;
5168         AttrNumber      attnum;
5169         Relation        attr_rel;
5170         List       *indexoidlist;
5171         ListCell   *indexoidscan;
5172         ObjectAddress address;
5173
5174         /*
5175          * lookup the attribute
5176          */
5177         attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
5178
5179         tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
5180
5181         if (!HeapTupleIsValid(tuple))
5182                 ereport(ERROR,
5183                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5184                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5185                                                 colName, RelationGetRelationName(rel))));
5186
5187         attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
5188
5189         /* Prevent them from altering a system attribute */
5190         if (attnum <= 0)
5191                 ereport(ERROR,
5192                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5193                                  errmsg("cannot alter system column \"%s\"",
5194                                                 colName)));
5195
5196         /*
5197          * Check that the attribute is not in a primary key
5198          *
5199          * Note: we'll throw error even if the pkey index is not valid.
5200          */
5201
5202         /* Loop over all indexes on the relation */
5203         indexoidlist = RelationGetIndexList(rel);
5204
5205         foreach(indexoidscan, indexoidlist)
5206         {
5207                 Oid                     indexoid = lfirst_oid(indexoidscan);
5208                 HeapTuple       indexTuple;
5209                 Form_pg_index indexStruct;
5210                 int                     i;
5211
5212                 indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
5213                 if (!HeapTupleIsValid(indexTuple))
5214                         elog(ERROR, "cache lookup failed for index %u", indexoid);
5215                 indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
5216
5217                 /* If the index is not a primary key, skip the check */
5218                 if (indexStruct->indisprimary)
5219                 {
5220                         /*
5221                          * Loop over each attribute in the primary key and see if it
5222                          * matches the to-be-altered attribute
5223                          */
5224                         for (i = 0; i < indexStruct->indnatts; i++)
5225                         {
5226                                 if (indexStruct->indkey.values[i] == attnum)
5227                                         ereport(ERROR,
5228                                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5229                                                          errmsg("column \"%s\" is in a primary key",
5230                                                                         colName)));
5231                         }
5232                 }
5233
5234                 ReleaseSysCache(indexTuple);
5235         }
5236
5237         list_free(indexoidlist);
5238
5239         /*
5240          * Okay, actually perform the catalog change ... if needed
5241          */
5242         if (((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull)
5243         {
5244                 ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = FALSE;
5245
5246                 simple_heap_update(attr_rel, &tuple->t_self, tuple);
5247
5248                 /* keep the system catalog indexes current */
5249                 CatalogUpdateIndexes(attr_rel, tuple);
5250
5251                 ObjectAddressSubSet(address, RelationRelationId,
5252                                                         RelationGetRelid(rel), attnum);
5253         }
5254         else
5255                 address = InvalidObjectAddress;
5256
5257         InvokeObjectPostAlterHook(RelationRelationId,
5258                                                           RelationGetRelid(rel), attnum);
5259
5260         heap_close(attr_rel, RowExclusiveLock);
5261
5262         return address;
5263 }
5264
5265 /*
5266  * ALTER TABLE ALTER COLUMN SET NOT NULL
5267  *
5268  * Return the address of the modified column.  If the column was already NOT
5269  * NULL, InvalidObjectAddress is returned.
5270  */
5271 static ObjectAddress
5272 ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
5273                                  const char *colName, LOCKMODE lockmode)
5274 {
5275         HeapTuple       tuple;
5276         AttrNumber      attnum;
5277         Relation        attr_rel;
5278         ObjectAddress address;
5279
5280         /*
5281          * lookup the attribute
5282          */
5283         attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
5284
5285         tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
5286
5287         if (!HeapTupleIsValid(tuple))
5288                 ereport(ERROR,
5289                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5290                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5291                                                 colName, RelationGetRelationName(rel))));
5292
5293         attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
5294
5295         /* Prevent them from altering a system attribute */
5296         if (attnum <= 0)
5297                 ereport(ERROR,
5298                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5299                                  errmsg("cannot alter system column \"%s\"",
5300                                                 colName)));
5301
5302         /*
5303          * Okay, actually perform the catalog change ... if needed
5304          */
5305         if (!((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull)
5306         {
5307                 ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = TRUE;
5308
5309                 simple_heap_update(attr_rel, &tuple->t_self, tuple);
5310
5311                 /* keep the system catalog indexes current */
5312                 CatalogUpdateIndexes(attr_rel, tuple);
5313
5314                 /* Tell Phase 3 it needs to test the constraint */
5315                 tab->new_notnull = true;
5316
5317                 ObjectAddressSubSet(address, RelationRelationId,
5318                                                         RelationGetRelid(rel), attnum);
5319         }
5320         else
5321                 address = InvalidObjectAddress;
5322
5323         InvokeObjectPostAlterHook(RelationRelationId,
5324                                                           RelationGetRelid(rel), attnum);
5325
5326         heap_close(attr_rel, RowExclusiveLock);
5327
5328         return address;
5329 }
5330
5331 /*
5332  * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT
5333  *
5334  * Return the address of the affected column.
5335  */
5336 static ObjectAddress
5337 ATExecColumnDefault(Relation rel, const char *colName,
5338                                         Node *newDefault, LOCKMODE lockmode)
5339 {
5340         AttrNumber      attnum;
5341         ObjectAddress address;
5342
5343         /*
5344          * get the number of the attribute
5345          */
5346         attnum = get_attnum(RelationGetRelid(rel), colName);
5347         if (attnum == InvalidAttrNumber)
5348                 ereport(ERROR,
5349                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5350                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5351                                                 colName, RelationGetRelationName(rel))));
5352
5353         /* Prevent them from altering a system attribute */
5354         if (attnum <= 0)
5355                 ereport(ERROR,
5356                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5357                                  errmsg("cannot alter system column \"%s\"",
5358                                                 colName)));
5359
5360         /*
5361          * Remove any old default for the column.  We use RESTRICT here for
5362          * safety, but at present we do not expect anything to depend on the
5363          * default.
5364          *
5365          * We treat removing the existing default as an internal operation when it
5366          * is preparatory to adding a new default, but as a user-initiated
5367          * operation when the user asked for a drop.
5368          */
5369         RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false,
5370                                           newDefault == NULL ? false : true);
5371
5372         if (newDefault)
5373         {
5374                 /* SET DEFAULT */
5375                 RawColumnDefault *rawEnt;
5376
5377                 rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
5378                 rawEnt->attnum = attnum;
5379                 rawEnt->raw_default = newDefault;
5380
5381                 /*
5382                  * This function is intended for CREATE TABLE, so it processes a
5383                  * _list_ of defaults, but we just do one.
5384                  */
5385                 AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
5386                                                                   false, true, false);
5387         }
5388
5389         ObjectAddressSubSet(address, RelationRelationId,
5390                                                 RelationGetRelid(rel), attnum);
5391         return address;
5392 }
5393
5394 /*
5395  * ALTER TABLE ALTER COLUMN SET STATISTICS
5396  */
5397 static void
5398 ATPrepSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
5399 {
5400         /*
5401          * We do our own permission checking because (a) we want to allow SET
5402          * STATISTICS on indexes (for expressional index columns), and (b) we want
5403          * to allow SET STATISTICS on system catalogs without requiring
5404          * allowSystemTableMods to be turned on.
5405          */
5406         if (rel->rd_rel->relkind != RELKIND_RELATION &&
5407                 rel->rd_rel->relkind != RELKIND_MATVIEW &&
5408                 rel->rd_rel->relkind != RELKIND_INDEX &&
5409                 rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
5410                 ereport(ERROR,
5411                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5412                                  errmsg("\"%s\" is not a table, materialized view, index, or foreign table",
5413                                                 RelationGetRelationName(rel))));
5414
5415         /* Permissions checks */
5416         if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
5417                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
5418                                            RelationGetRelationName(rel));
5419 }
5420
5421 /*
5422  * Return value is the address of the modified column
5423  */
5424 static ObjectAddress
5425 ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
5426 {
5427         int                     newtarget;
5428         Relation        attrelation;
5429         HeapTuple       tuple;
5430         Form_pg_attribute attrtuple;
5431         AttrNumber      attnum;
5432         ObjectAddress address;
5433
5434         Assert(IsA(newValue, Integer));
5435         newtarget = intVal(newValue);
5436
5437         /*
5438          * Limit target to a sane range
5439          */
5440         if (newtarget < -1)
5441         {
5442                 ereport(ERROR,
5443                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5444                                  errmsg("statistics target %d is too low",
5445                                                 newtarget)));
5446         }
5447         else if (newtarget > 10000)
5448         {
5449                 newtarget = 10000;
5450                 ereport(WARNING,
5451                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5452                                  errmsg("lowering statistics target to %d",
5453                                                 newtarget)));
5454         }
5455
5456         attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
5457
5458         tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
5459
5460         if (!HeapTupleIsValid(tuple))
5461                 ereport(ERROR,
5462                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5463                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5464                                                 colName, RelationGetRelationName(rel))));
5465         attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
5466
5467         attnum = attrtuple->attnum;
5468         if (attnum <= 0)
5469                 ereport(ERROR,
5470                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5471                                  errmsg("cannot alter system column \"%s\"",
5472                                                 colName)));
5473
5474         attrtuple->attstattarget = newtarget;
5475
5476         simple_heap_update(attrelation, &tuple->t_self, tuple);
5477
5478         /* keep system catalog indexes current */
5479         CatalogUpdateIndexes(attrelation, tuple);
5480
5481         InvokeObjectPostAlterHook(RelationRelationId,
5482                                                           RelationGetRelid(rel),
5483                                                           attrtuple->attnum);
5484         ObjectAddressSubSet(address, RelationRelationId,
5485                                                 RelationGetRelid(rel), attnum);
5486         heap_freetuple(tuple);
5487
5488         heap_close(attrelation, RowExclusiveLock);
5489
5490         return address;
5491 }
5492
5493 /*
5494  * Return value is the address of the modified column
5495  */
5496 static ObjectAddress
5497 ATExecSetOptions(Relation rel, const char *colName, Node *options,
5498                                  bool isReset, LOCKMODE lockmode)
5499 {
5500         Relation        attrelation;
5501         HeapTuple       tuple,
5502                                 newtuple;
5503         Form_pg_attribute attrtuple;
5504         AttrNumber      attnum;
5505         Datum           datum,
5506                                 newOptions;
5507         bool            isnull;
5508         ObjectAddress address;
5509         Datum           repl_val[Natts_pg_attribute];
5510         bool            repl_null[Natts_pg_attribute];
5511         bool            repl_repl[Natts_pg_attribute];
5512
5513         attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
5514
5515         tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
5516
5517         if (!HeapTupleIsValid(tuple))
5518                 ereport(ERROR,
5519                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5520                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5521                                                 colName, RelationGetRelationName(rel))));
5522         attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
5523
5524         attnum = attrtuple->attnum;
5525         if (attnum <= 0)
5526                 ereport(ERROR,
5527                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5528                                  errmsg("cannot alter system column \"%s\"",
5529                                                 colName)));
5530
5531         /* Generate new proposed attoptions (text array) */
5532         Assert(IsA(options, List));
5533         datum = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
5534                                                         &isnull);
5535         newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
5536                                                                          (List *) options, NULL, NULL, false,
5537                                                                          isReset);
5538         /* Validate new options */
5539         (void) attribute_reloptions(newOptions, true);
5540
5541         /* Build new tuple. */
5542         memset(repl_null, false, sizeof(repl_null));
5543         memset(repl_repl, false, sizeof(repl_repl));
5544         if (newOptions != (Datum) 0)
5545                 repl_val[Anum_pg_attribute_attoptions - 1] = newOptions;
5546         else
5547                 repl_null[Anum_pg_attribute_attoptions - 1] = true;
5548         repl_repl[Anum_pg_attribute_attoptions - 1] = true;
5549         newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation),
5550                                                                  repl_val, repl_null, repl_repl);
5551
5552         /* Update system catalog. */
5553         simple_heap_update(attrelation, &newtuple->t_self, newtuple);
5554         CatalogUpdateIndexes(attrelation, newtuple);
5555
5556         InvokeObjectPostAlterHook(RelationRelationId,
5557                                                           RelationGetRelid(rel),
5558                                                           attrtuple->attnum);
5559         ObjectAddressSubSet(address, RelationRelationId,
5560                                                 RelationGetRelid(rel), attnum);
5561
5562         heap_freetuple(newtuple);
5563
5564         ReleaseSysCache(tuple);
5565
5566         heap_close(attrelation, RowExclusiveLock);
5567
5568         return address;
5569 }
5570
5571 /*
5572  * ALTER TABLE ALTER COLUMN SET STORAGE
5573  *
5574  * Return value is the address of the modified column
5575  */
5576 static ObjectAddress
5577 ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
5578 {
5579         char       *storagemode;
5580         char            newstorage;
5581         Relation        attrelation;
5582         HeapTuple       tuple;
5583         Form_pg_attribute attrtuple;
5584         AttrNumber      attnum;
5585         ObjectAddress address;
5586
5587         Assert(IsA(newValue, String));
5588         storagemode = strVal(newValue);
5589
5590         if (pg_strcasecmp(storagemode, "plain") == 0)
5591                 newstorage = 'p';
5592         else if (pg_strcasecmp(storagemode, "external") == 0)
5593                 newstorage = 'e';
5594         else if (pg_strcasecmp(storagemode, "extended") == 0)
5595                 newstorage = 'x';
5596         else if (pg_strcasecmp(storagemode, "main") == 0)
5597                 newstorage = 'm';
5598         else
5599         {
5600                 ereport(ERROR,
5601                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5602                                  errmsg("invalid storage type \"%s\"",
5603                                                 storagemode)));
5604                 newstorage = 0;                 /* keep compiler quiet */
5605         }
5606
5607         attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
5608
5609         tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
5610
5611         if (!HeapTupleIsValid(tuple))
5612                 ereport(ERROR,
5613                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
5614                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
5615                                                 colName, RelationGetRelationName(rel))));
5616         attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
5617
5618         attnum = attrtuple->attnum;
5619         if (attnum <= 0)
5620                 ereport(ERROR,
5621                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5622                                  errmsg("cannot alter system column \"%s\"",
5623                                                 colName)));
5624
5625         /*
5626          * safety check: do not allow toasted storage modes unless column datatype
5627          * is TOAST-aware.
5628          */
5629         if (newstorage == 'p' || TypeIsToastable(attrtuple->atttypid))
5630                 attrtuple->attstorage = newstorage;
5631         else
5632                 ereport(ERROR,
5633                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5634                                  errmsg("column data type %s can only have storage PLAIN",
5635                                                 format_type_be(attrtuple->atttypid))));
5636
5637         simple_heap_update(attrelation, &tuple->t_self, tuple);
5638
5639         /* keep system catalog indexes current */
5640         CatalogUpdateIndexes(attrelation, tuple);
5641
5642         InvokeObjectPostAlterHook(RelationRelationId,
5643                                                           RelationGetRelid(rel),
5644                                                           attrtuple->attnum);
5645
5646         heap_freetuple(tuple);
5647
5648         heap_close(attrelation, RowExclusiveLock);
5649
5650         ObjectAddressSubSet(address, RelationRelationId,
5651                                                 RelationGetRelid(rel), attnum);
5652         return address;
5653 }
5654
5655
5656 /*
5657  * ALTER TABLE DROP COLUMN
5658  *
5659  * DROP COLUMN cannot use the normal ALTER TABLE recursion mechanism,
5660  * because we have to decide at runtime whether to recurse or not depending
5661  * on whether attinhcount goes to zero or not.  (We can't check this in a
5662  * static pre-pass because it won't handle multiple inheritance situations
5663  * correctly.)
5664  */
5665 static void
5666 ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
5667                                  AlterTableCmd *cmd, LOCKMODE lockmode)
5668 {
5669         if (rel->rd_rel->reloftype && !recursing)
5670                 ereport(ERROR,
5671                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5672                                  errmsg("cannot drop column from typed table")));
5673
5674         if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
5675                 ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
5676
5677         if (recurse)
5678                 cmd->subtype = AT_DropColumnRecurse;
5679 }
5680
5681 /*
5682  * Return value is the address of the dropped column.
5683  */
5684 static ObjectAddress
5685 ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
5686                                  DropBehavior behavior,
5687                                  bool recurse, bool recursing,
5688                                  bool missing_ok, LOCKMODE lockmode)
5689 {
5690         HeapTuple       tuple;
5691         Form_pg_attribute targetatt;
5692         AttrNumber      attnum;
5693         List       *children;
5694         ObjectAddress object;
5695
5696         /* At top level, permission check was done in ATPrepCmd, else do it */
5697         if (recursing)
5698                 ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
5699
5700         /*
5701          * get the number of the attribute
5702          */
5703         tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
5704         if (!HeapTupleIsValid(tuple))
5705         {
5706                 if (!missing_ok)
5707                 {
5708                         ereport(ERROR,
5709                                         (errcode(ERRCODE_UNDEFINED_COLUMN),
5710                                          errmsg("column \"%s\" of relation \"%s\" does not exist",
5711                                                         colName, RelationGetRelationName(rel))));
5712                 }
5713                 else
5714                 {
5715                         ereport(NOTICE,
5716                                         (errmsg("column \"%s\" of relation \"%s\" does not exist, skipping",
5717                                                         colName, RelationGetRelationName(rel))));
5718                         return InvalidObjectAddress;
5719                 }
5720         }
5721         targetatt = (Form_pg_attribute) GETSTRUCT(tuple);
5722
5723         attnum = targetatt->attnum;
5724
5725         /* Can't drop a system attribute, except OID */
5726         if (attnum <= 0 && attnum != ObjectIdAttributeNumber)
5727                 ereport(ERROR,
5728                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5729                                  errmsg("cannot drop system column \"%s\"",
5730                                                 colName)));
5731
5732         /* Don't drop inherited columns */
5733         if (targetatt->attinhcount > 0 && !recursing)
5734                 ereport(ERROR,
5735                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5736                                  errmsg("cannot drop inherited column \"%s\"",
5737                                                 colName)));
5738
5739         ReleaseSysCache(tuple);
5740
5741         /*
5742          * Propagate to children as appropriate.  Unlike most other ALTER
5743          * routines, we have to do this one level of recursion at a time; we can't
5744          * use find_all_inheritors to do it in one pass.
5745          */
5746         children = find_inheritance_children(RelationGetRelid(rel), lockmode);
5747
5748         if (children)
5749         {
5750                 Relation        attr_rel;
5751                 ListCell   *child;
5752
5753                 attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
5754                 foreach(child, children)
5755                 {
5756                         Oid                     childrelid = lfirst_oid(child);
5757                         Relation        childrel;
5758                         Form_pg_attribute childatt;
5759
5760                         /* find_inheritance_children already got lock */
5761                         childrel = heap_open(childrelid, NoLock);
5762                         CheckTableNotInUse(childrel, "ALTER TABLE");
5763
5764                         tuple = SearchSysCacheCopyAttName(childrelid, colName);
5765                         if (!HeapTupleIsValid(tuple))           /* shouldn't happen */
5766                                 elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u",
5767                                          colName, childrelid);
5768                         childatt = (Form_pg_attribute) GETSTRUCT(tuple);
5769
5770                         if (childatt->attinhcount <= 0)         /* shouldn't happen */
5771                                 elog(ERROR, "relation %u has non-inherited attribute \"%s\"",
5772                                          childrelid, colName);
5773
5774                         if (recurse)
5775                         {
5776                                 /*
5777                                  * If the child column has other definition sources, just
5778                                  * decrement its inheritance count; if not, recurse to delete
5779                                  * it.
5780                                  */
5781                                 if (childatt->attinhcount == 1 && !childatt->attislocal)
5782                                 {
5783                                         /* Time to delete this child column, too */
5784                                         ATExecDropColumn(wqueue, childrel, colName,
5785                                                                          behavior, true, true,
5786                                                                          false, lockmode);
5787                                 }
5788                                 else
5789                                 {
5790                                         /* Child column must survive my deletion */
5791                                         childatt->attinhcount--;
5792
5793                                         simple_heap_update(attr_rel, &tuple->t_self, tuple);
5794
5795                                         /* keep the system catalog indexes current */
5796                                         CatalogUpdateIndexes(attr_rel, tuple);
5797
5798                                         /* Make update visible */
5799                                         CommandCounterIncrement();
5800                                 }
5801                         }
5802                         else
5803                         {
5804                                 /*
5805                                  * If we were told to drop ONLY in this table (no recursion),
5806                                  * we need to mark the inheritors' attributes as locally
5807                                  * defined rather than inherited.
5808                                  */
5809                                 childatt->attinhcount--;
5810                                 childatt->attislocal = true;
5811
5812                                 simple_heap_update(attr_rel, &tuple->t_self, tuple);
5813
5814                                 /* keep the system catalog indexes current */
5815                                 CatalogUpdateIndexes(attr_rel, tuple);
5816
5817                                 /* Make update visible */
5818                                 CommandCounterIncrement();
5819                         }
5820
5821                         heap_freetuple(tuple);
5822
5823                         heap_close(childrel, NoLock);
5824                 }
5825                 heap_close(attr_rel, RowExclusiveLock);
5826         }
5827
5828         /*
5829          * Perform the actual column deletion
5830          */
5831         object.classId = RelationRelationId;
5832         object.objectId = RelationGetRelid(rel);
5833         object.objectSubId = attnum;
5834
5835         performDeletion(&object, behavior, 0);
5836
5837         /*
5838          * If we dropped the OID column, must adjust pg_class.relhasoids and tell
5839          * Phase 3 to physically get rid of the column.  We formerly left the
5840          * column in place physically, but this caused subtle problems.  See
5841          * http://archives.postgresql.org/pgsql-hackers/2009-02/msg00363.php
5842          */
5843         if (attnum == ObjectIdAttributeNumber)
5844         {
5845                 Relation        class_rel;
5846                 Form_pg_class tuple_class;
5847                 AlteredTableInfo *tab;
5848
5849                 class_rel = heap_open(RelationRelationId, RowExclusiveLock);
5850
5851                 tuple = SearchSysCacheCopy1(RELOID,
5852                                                                         ObjectIdGetDatum(RelationGetRelid(rel)));
5853                 if (!HeapTupleIsValid(tuple))
5854                         elog(ERROR, "cache lookup failed for relation %u",
5855                                  RelationGetRelid(rel));
5856                 tuple_class = (Form_pg_class) GETSTRUCT(tuple);
5857
5858                 tuple_class->relhasoids = false;
5859                 simple_heap_update(class_rel, &tuple->t_self, tuple);
5860
5861                 /* Keep the catalog indexes up to date */
5862                 CatalogUpdateIndexes(class_rel, tuple);
5863
5864                 heap_close(class_rel, RowExclusiveLock);
5865
5866                 /* Find or create work queue entry for this table */
5867                 tab = ATGetQueueEntry(wqueue, rel);
5868
5869                 /* Tell Phase 3 to physically remove the OID column */
5870                 tab->rewrite |= AT_REWRITE_ALTER_OID;
5871         }
5872
5873         return object;
5874 }
5875
5876 /*
5877  * ALTER TABLE ADD INDEX
5878  *
5879  * There is no such command in the grammar, but parse_utilcmd.c converts
5880  * UNIQUE and PRIMARY KEY constraints into AT_AddIndex subcommands.  This lets
5881  * us schedule creation of the index at the appropriate time during ALTER.
5882  *
5883  * Return value is the address of the new index.
5884  */
5885 static ObjectAddress
5886 ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
5887                            IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode)
5888 {
5889         bool            check_rights;
5890         bool            skip_build;
5891         bool            quiet;
5892         ObjectAddress address;
5893
5894         Assert(IsA(stmt, IndexStmt));
5895         Assert(!stmt->concurrent);
5896
5897         /* The IndexStmt has already been through transformIndexStmt */
5898         Assert(stmt->transformed);
5899
5900         /* suppress schema rights check when rebuilding existing index */
5901         check_rights = !is_rebuild;
5902         /* skip index build if phase 3 will do it or we're reusing an old one */
5903         skip_build = tab->rewrite > 0 || OidIsValid(stmt->oldNode);
5904         /* suppress notices when rebuilding existing index */
5905         quiet = is_rebuild;
5906
5907         address = DefineIndex(RelationGetRelid(rel),
5908                                                   stmt,
5909                                                   InvalidOid,   /* no predefined OID */
5910                                                   true, /* is_alter_table */
5911                                                   check_rights,
5912                                                   skip_build,
5913                                                   quiet);
5914
5915         /*
5916          * If TryReuseIndex() stashed a relfilenode for us, we used it for the new
5917          * index instead of building from scratch.  The DROP of the old edition of
5918          * this index will have scheduled the storage for deletion at commit, so
5919          * cancel that pending deletion.
5920          */
5921         if (OidIsValid(stmt->oldNode))
5922         {
5923                 Relation        irel = index_open(address.objectId, NoLock);
5924
5925                 RelationPreserveStorage(irel->rd_node, true);
5926                 index_close(irel, NoLock);
5927         }
5928
5929         return address;
5930 }
5931
5932 /*
5933  * ALTER TABLE ADD CONSTRAINT USING INDEX
5934  *
5935  * Returns the address of the new constraint.
5936  */
5937 static ObjectAddress
5938 ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
5939                                                  IndexStmt *stmt, LOCKMODE lockmode)
5940 {
5941         Oid                     index_oid = stmt->indexOid;
5942         Relation        indexRel;
5943         char       *indexName;
5944         IndexInfo  *indexInfo;
5945         char       *constraintName;
5946         char            constraintType;
5947         ObjectAddress address;
5948
5949         Assert(IsA(stmt, IndexStmt));
5950         Assert(OidIsValid(index_oid));
5951         Assert(stmt->isconstraint);
5952
5953         indexRel = index_open(index_oid, AccessShareLock);
5954
5955         indexName = pstrdup(RelationGetRelationName(indexRel));
5956
5957         indexInfo = BuildIndexInfo(indexRel);
5958
5959         /* this should have been checked at parse time */
5960         if (!indexInfo->ii_Unique)
5961                 elog(ERROR, "index \"%s\" is not unique", indexName);
5962
5963         /*
5964          * Determine name to assign to constraint.  We require a constraint to
5965          * have the same name as the underlying index; therefore, use the index's
5966          * existing name as the default constraint name, and if the user
5967          * explicitly gives some other name for the constraint, rename the index
5968          * to match.
5969          */
5970         constraintName = stmt->idxname;
5971         if (constraintName == NULL)
5972                 constraintName = indexName;
5973         else if (strcmp(constraintName, indexName) != 0)
5974         {
5975                 ereport(NOTICE,
5976                                 (errmsg("ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"",
5977                                                 indexName, constraintName)));
5978                 RenameRelationInternal(index_oid, constraintName, false);
5979         }
5980
5981         /* Extra checks needed if making primary key */
5982         if (stmt->primary)
5983                 index_check_primary_key(rel, indexInfo, true);
5984
5985         /* Note we currently don't support EXCLUSION constraints here */
5986         if (stmt->primary)
5987                 constraintType = CONSTRAINT_PRIMARY;
5988         else
5989                 constraintType = CONSTRAINT_UNIQUE;
5990
5991         /* Create the catalog entries for the constraint */
5992         address = index_constraint_create(rel,
5993                                                                           index_oid,
5994                                                                           indexInfo,
5995                                                                           constraintName,
5996                                                                           constraintType,
5997                                                                           stmt->deferrable,
5998                                                                           stmt->initdeferred,
5999                                                                           stmt->primary,
6000                                                                           true,         /* update pg_index */
6001                                                                           true,         /* remove old dependencies */
6002                                                                           allowSystemTableMods,
6003                                                                           false);       /* is_internal */
6004
6005         index_close(indexRel, NoLock);
6006
6007         return address;
6008 }
6009
6010 /*
6011  * ALTER TABLE ADD CONSTRAINT
6012  *
6013  * Return value is the address of the new constraint; if no constraint was
6014  * added, InvalidObjectAddress is returned.
6015  */
6016 static ObjectAddress
6017 ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
6018                                         Constraint *newConstraint, bool recurse, bool is_readd,
6019                                         LOCKMODE lockmode)
6020 {
6021         ObjectAddress address = InvalidObjectAddress;
6022
6023         Assert(IsA(newConstraint, Constraint));
6024
6025         /*
6026          * Currently, we only expect to see CONSTR_CHECK and CONSTR_FOREIGN nodes
6027          * arriving here (see the preprocessing done in parse_utilcmd.c).  Use a
6028          * switch anyway to make it easier to add more code later.
6029          */
6030         switch (newConstraint->contype)
6031         {
6032                 case CONSTR_CHECK:
6033                         address =
6034                                 ATAddCheckConstraint(wqueue, tab, rel,
6035                                                                          newConstraint, recurse, false, is_readd,
6036                                                                          lockmode);
6037                         break;
6038
6039                 case CONSTR_FOREIGN:
6040
6041                         /*
6042                          * Note that we currently never recurse for FK constraints, so the
6043                          * "recurse" flag is silently ignored.
6044                          *
6045                          * Assign or validate constraint name
6046                          */
6047                         if (newConstraint->conname)
6048                         {
6049                                 if (ConstraintNameIsUsed(CONSTRAINT_RELATION,
6050                                                                                  RelationGetRelid(rel),
6051                                                                                  RelationGetNamespace(rel),
6052                                                                                  newConstraint->conname))
6053                                         ereport(ERROR,
6054                                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
6055                                                          errmsg("constraint \"%s\" for relation \"%s\" already exists",
6056                                                                         newConstraint->conname,
6057                                                                         RelationGetRelationName(rel))));
6058                         }
6059                         else
6060                                 newConstraint->conname =
6061                                         ChooseConstraintName(RelationGetRelationName(rel),
6062                                                                    strVal(linitial(newConstraint->fk_attrs)),
6063                                                                                  "fkey",
6064                                                                                  RelationGetNamespace(rel),
6065                                                                                  NIL);
6066
6067                         address = ATAddForeignKeyConstraint(tab, rel, newConstraint,
6068                                                                                                 lockmode);
6069                         break;
6070
6071                 default:
6072                         elog(ERROR, "unrecognized constraint type: %d",
6073                                  (int) newConstraint->contype);
6074         }
6075
6076         return address;
6077 }
6078
6079 /*
6080  * Add a check constraint to a single table and its children.  Returns the
6081  * address of the constraint added to the parent relation, if one gets added,
6082  * or InvalidObjectAddress otherwise.
6083  *
6084  * Subroutine for ATExecAddConstraint.
6085  *
6086  * We must recurse to child tables during execution, rather than using
6087  * ALTER TABLE's normal prep-time recursion.  The reason is that all the
6088  * constraints *must* be given the same name, else they won't be seen as
6089  * related later.  If the user didn't explicitly specify a name, then
6090  * AddRelationNewConstraints would normally assign different names to the
6091  * child constraints.  To fix that, we must capture the name assigned at
6092  * the parent table and pass that down.
6093  *
6094  * When re-adding a previously existing constraint (during ALTER COLUMN TYPE),
6095  * we don't need to recurse here, because recursion will be carried out at a
6096  * higher level; the constraint name issue doesn't apply because the names
6097  * have already been assigned and are just being re-used.  We need a separate
6098  * "is_readd" flag for that; just setting recurse=false would result in an
6099  * error if there are child tables.
6100  */
6101 static ObjectAddress
6102 ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
6103                                          Constraint *constr, bool recurse, bool recursing,
6104                                          bool is_readd, LOCKMODE lockmode)
6105 {
6106         List       *newcons;
6107         ListCell   *lcon;
6108         List       *children;
6109         ListCell   *child;
6110         ObjectAddress address = InvalidObjectAddress;
6111
6112         /* At top level, permission check was done in ATPrepCmd, else do it */
6113         if (recursing)
6114                 ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
6115
6116         /*
6117          * Call AddRelationNewConstraints to do the work, making sure it works on
6118          * a copy of the Constraint so transformExpr can't modify the original. It
6119          * returns a list of cooked constraints.
6120          *
6121          * If the constraint ends up getting merged with a pre-existing one, it's
6122          * omitted from the returned list, which is what we want: we do not need
6123          * to do any validation work.  That can only happen at child tables,
6124          * though, since we disallow merging at the top level.
6125          */
6126         newcons = AddRelationNewConstraints(rel, NIL,
6127                                                                                 list_make1(copyObject(constr)),
6128                                                                                 recursing,              /* allow_merge */
6129                                                                                 !recursing,             /* is_local */
6130                                                                                 is_readd);              /* is_internal */
6131
6132         /* we don't expect more than one constraint here */
6133         Assert(list_length(newcons) <= 1);
6134
6135         /* Add each to-be-validated constraint to Phase 3's queue */
6136         foreach(lcon, newcons)
6137         {
6138                 CookedConstraint *ccon = (CookedConstraint *) lfirst(lcon);
6139
6140                 if (!ccon->skip_validation)
6141                 {
6142                         NewConstraint *newcon;
6143
6144                         newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
6145                         newcon->name = ccon->name;
6146                         newcon->contype = ccon->contype;
6147                         /* ExecQual wants implicit-AND format */
6148                         newcon->qual = (Node *) make_ands_implicit((Expr *) ccon->expr);
6149
6150                         tab->constraints = lappend(tab->constraints, newcon);
6151                 }
6152
6153                 /* Save the actually assigned name if it was defaulted */
6154                 if (constr->conname == NULL)
6155                         constr->conname = ccon->name;
6156
6157                 ObjectAddressSet(address, ConstraintRelationId, ccon->conoid);
6158         }
6159
6160         /* At this point we must have a locked-down name to use */
6161         Assert(constr->conname != NULL);
6162
6163         /* Advance command counter in case same table is visited multiple times */
6164         CommandCounterIncrement();
6165
6166         /*
6167          * If the constraint got merged with an existing constraint, we're done.
6168          * We mustn't recurse to child tables in this case, because they've
6169          * already got the constraint, and visiting them again would lead to an
6170          * incorrect value for coninhcount.
6171          */
6172         if (newcons == NIL)
6173                 return address;
6174
6175         /*
6176          * If adding a NO INHERIT constraint, no need to find our children.
6177          * Likewise, in a re-add operation, we don't need to recurse (that will be
6178          * handled at higher levels).
6179          */
6180         if (constr->is_no_inherit || is_readd)
6181                 return address;
6182
6183         /*
6184          * Propagate to children as appropriate.  Unlike most other ALTER
6185          * routines, we have to do this one level of recursion at a time; we can't
6186          * use find_all_inheritors to do it in one pass.
6187          */
6188         children = find_inheritance_children(RelationGetRelid(rel), lockmode);
6189
6190         /*
6191          * Check if ONLY was specified with ALTER TABLE.  If so, allow the
6192          * contraint creation only if there are no children currently.  Error out
6193          * otherwise.
6194          */
6195         if (!recurse && children != NIL)
6196                 ereport(ERROR,
6197                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6198                                  errmsg("constraint must be added to child tables too")));
6199
6200         foreach(child, children)
6201         {
6202                 Oid                     childrelid = lfirst_oid(child);
6203                 Relation        childrel;
6204                 AlteredTableInfo *childtab;
6205
6206                 /* find_inheritance_children already got lock */
6207                 childrel = heap_open(childrelid, NoLock);
6208                 CheckTableNotInUse(childrel, "ALTER TABLE");
6209
6210                 /* Find or create work queue entry for this table */
6211                 childtab = ATGetQueueEntry(wqueue, childrel);
6212
6213                 /* Recurse to child */
6214                 ATAddCheckConstraint(wqueue, childtab, childrel,
6215                                                          constr, recurse, true, is_readd, lockmode);
6216
6217                 heap_close(childrel, NoLock);
6218         }
6219
6220         return address;
6221 }
6222
6223 /*
6224  * Add a foreign-key constraint to a single table; return the new constraint's
6225  * address.
6226  *
6227  * Subroutine for ATExecAddConstraint.  Must already hold exclusive
6228  * lock on the rel, and have done appropriate validity checks for it.
6229  * We do permissions checks here, however.
6230  */
6231 static ObjectAddress
6232 ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
6233                                                   Constraint *fkconstraint, LOCKMODE lockmode)
6234 {
6235         Relation        pkrel;
6236         int16           pkattnum[INDEX_MAX_KEYS];
6237         int16           fkattnum[INDEX_MAX_KEYS];
6238         Oid                     pktypoid[INDEX_MAX_KEYS];
6239         Oid                     fktypoid[INDEX_MAX_KEYS];
6240         Oid                     opclasses[INDEX_MAX_KEYS];
6241         Oid                     pfeqoperators[INDEX_MAX_KEYS];
6242         Oid                     ppeqoperators[INDEX_MAX_KEYS];
6243         Oid                     ffeqoperators[INDEX_MAX_KEYS];
6244         int                     i;
6245         int                     numfks,
6246                                 numpks;
6247         Oid                     indexOid;
6248         Oid                     constrOid;
6249         bool            old_check_ok;
6250         ObjectAddress address;
6251         ListCell   *old_pfeqop_item = list_head(fkconstraint->old_conpfeqop);
6252
6253         /*
6254          * Grab ShareRowExclusiveLock on the pk table, so that someone doesn't
6255          * delete rows out from under us.
6256          */
6257         if (OidIsValid(fkconstraint->old_pktable_oid))
6258                 pkrel = heap_open(fkconstraint->old_pktable_oid, ShareRowExclusiveLock);
6259         else
6260                 pkrel = heap_openrv(fkconstraint->pktable, ShareRowExclusiveLock);
6261
6262         /*
6263          * Validity checks (permission checks wait till we have the column
6264          * numbers)
6265          */
6266         if (pkrel->rd_rel->relkind != RELKIND_RELATION)
6267                 ereport(ERROR,
6268                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
6269                                  errmsg("referenced relation \"%s\" is not a table",
6270                                                 RelationGetRelationName(pkrel))));
6271
6272         if (!allowSystemTableMods && IsSystemRelation(pkrel))
6273                 ereport(ERROR,
6274                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
6275                                  errmsg("permission denied: \"%s\" is a system catalog",
6276                                                 RelationGetRelationName(pkrel))));
6277
6278         /*
6279          * References from permanent or unlogged tables to temp tables, and from
6280          * permanent tables to unlogged tables, are disallowed because the
6281          * referenced data can vanish out from under us.  References from temp
6282          * tables to any other table type are also disallowed, because other
6283          * backends might need to run the RI triggers on the perm table, but they
6284          * can't reliably see tuples in the local buffers of other backends.
6285          */
6286         switch (rel->rd_rel->relpersistence)
6287         {
6288                 case RELPERSISTENCE_PERMANENT:
6289                         if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT)
6290                                 ereport(ERROR,
6291                                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6292                                                  errmsg("constraints on permanent tables may reference only permanent tables")));
6293                         break;
6294                 case RELPERSISTENCE_UNLOGGED:
6295                         if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT
6296                                 && pkrel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED)
6297                                 ereport(ERROR,
6298                                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6299                                                  errmsg("constraints on unlogged tables may reference only permanent or unlogged tables")));
6300                         break;
6301                 case RELPERSISTENCE_TEMP:
6302                         if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_TEMP)
6303                                 ereport(ERROR,
6304                                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6305                                                  errmsg("constraints on temporary tables may reference only temporary tables")));
6306                         if (!pkrel->rd_islocaltemp || !rel->rd_islocaltemp)
6307                                 ereport(ERROR,
6308                                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6309                                                  errmsg("constraints on temporary tables must involve temporary tables of this session")));
6310                         break;
6311         }
6312
6313         /*
6314          * Look up the referencing attributes to make sure they exist, and record
6315          * their attnums and type OIDs.
6316          */
6317         MemSet(pkattnum, 0, sizeof(pkattnum));
6318         MemSet(fkattnum, 0, sizeof(fkattnum));
6319         MemSet(pktypoid, 0, sizeof(pktypoid));
6320         MemSet(fktypoid, 0, sizeof(fktypoid));
6321         MemSet(opclasses, 0, sizeof(opclasses));
6322         MemSet(pfeqoperators, 0, sizeof(pfeqoperators));
6323         MemSet(ppeqoperators, 0, sizeof(ppeqoperators));
6324         MemSet(ffeqoperators, 0, sizeof(ffeqoperators));
6325
6326         numfks = transformColumnNameList(RelationGetRelid(rel),
6327                                                                          fkconstraint->fk_attrs,
6328                                                                          fkattnum, fktypoid);
6329
6330         /*
6331          * If the attribute list for the referenced table was omitted, lookup the
6332          * definition of the primary key and use it.  Otherwise, validate the
6333          * supplied attribute list.  In either case, discover the index OID and
6334          * index opclasses, and the attnums and type OIDs of the attributes.
6335          */
6336         if (fkconstraint->pk_attrs == NIL)
6337         {
6338                 numpks = transformFkeyGetPrimaryKey(pkrel, &indexOid,
6339                                                                                         &fkconstraint->pk_attrs,
6340                                                                                         pkattnum, pktypoid,
6341                                                                                         opclasses);
6342         }
6343         else
6344         {
6345                 numpks = transformColumnNameList(RelationGetRelid(pkrel),
6346                                                                                  fkconstraint->pk_attrs,
6347                                                                                  pkattnum, pktypoid);
6348                 /* Look for an index matching the column list */
6349                 indexOid = transformFkeyCheckAttrs(pkrel, numpks, pkattnum,
6350                                                                                    opclasses);
6351         }
6352
6353         /*
6354          * Now we can check permissions.
6355          */
6356         checkFkeyPermissions(pkrel, pkattnum, numpks);
6357         checkFkeyPermissions(rel, fkattnum, numfks);
6358
6359         /*
6360          * Look up the equality operators to use in the constraint.
6361          *
6362          * Note that we have to be careful about the difference between the actual
6363          * PK column type and the opclass' declared input type, which might be
6364          * only binary-compatible with it.  The declared opcintype is the right
6365          * thing to probe pg_amop with.
6366          */
6367         if (numfks != numpks)
6368                 ereport(ERROR,
6369                                 (errcode(ERRCODE_INVALID_FOREIGN_KEY),
6370                                  errmsg("number of referencing and referenced columns for foreign key disagree")));
6371
6372         /*
6373          * On the strength of a previous constraint, we might avoid scanning
6374          * tables to validate this one.  See below.
6375          */
6376         old_check_ok = (fkconstraint->old_conpfeqop != NIL);
6377         Assert(!old_check_ok || numfks == list_length(fkconstraint->old_conpfeqop));
6378
6379         for (i = 0; i < numpks; i++)
6380         {
6381                 Oid                     pktype = pktypoid[i];
6382                 Oid                     fktype = fktypoid[i];
6383                 Oid                     fktyped;
6384                 HeapTuple       cla_ht;
6385                 Form_pg_opclass cla_tup;
6386                 Oid                     amid;
6387                 Oid                     opfamily;
6388                 Oid                     opcintype;
6389                 Oid                     pfeqop;
6390                 Oid                     ppeqop;
6391                 Oid                     ffeqop;
6392                 int16           eqstrategy;
6393                 Oid                     pfeqop_right;
6394
6395                 /* We need several fields out of the pg_opclass entry */
6396                 cla_ht = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclasses[i]));
6397                 if (!HeapTupleIsValid(cla_ht))
6398                         elog(ERROR, "cache lookup failed for opclass %u", opclasses[i]);
6399                 cla_tup = (Form_pg_opclass) GETSTRUCT(cla_ht);
6400                 amid = cla_tup->opcmethod;
6401                 opfamily = cla_tup->opcfamily;
6402                 opcintype = cla_tup->opcintype;
6403                 ReleaseSysCache(cla_ht);
6404
6405                 /*
6406                  * Check it's a btree; currently this can never fail since no other
6407                  * index AMs support unique indexes.  If we ever did have other types
6408                  * of unique indexes, we'd need a way to determine which operator
6409                  * strategy number is equality.  (Is it reasonable to insist that
6410                  * every such index AM use btree's number for equality?)
6411                  */
6412                 if (amid != BTREE_AM_OID)
6413                         elog(ERROR, "only b-tree indexes are supported for foreign keys");
6414                 eqstrategy = BTEqualStrategyNumber;
6415
6416                 /*
6417                  * There had better be a primary equality operator for the index.
6418                  * We'll use it for PK = PK comparisons.
6419                  */
6420                 ppeqop = get_opfamily_member(opfamily, opcintype, opcintype,
6421                                                                          eqstrategy);
6422
6423                 if (!OidIsValid(ppeqop))
6424                         elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
6425                                  eqstrategy, opcintype, opcintype, opfamily);
6426
6427                 /*
6428                  * Are there equality operators that take exactly the FK type? Assume
6429                  * we should look through any domain here.
6430                  */
6431                 fktyped = getBaseType(fktype);
6432
6433                 pfeqop = get_opfamily_member(opfamily, opcintype, fktyped,
6434                                                                          eqstrategy);
6435                 if (OidIsValid(pfeqop))
6436                 {
6437                         pfeqop_right = fktyped;
6438                         ffeqop = get_opfamily_member(opfamily, fktyped, fktyped,
6439                                                                                  eqstrategy);
6440                 }
6441                 else
6442                 {
6443                         /* keep compiler quiet */
6444                         pfeqop_right = InvalidOid;
6445                         ffeqop = InvalidOid;
6446                 }
6447
6448                 if (!(OidIsValid(pfeqop) && OidIsValid(ffeqop)))
6449                 {
6450                         /*
6451                          * Otherwise, look for an implicit cast from the FK type to the
6452                          * opcintype, and if found, use the primary equality operator.
6453                          * This is a bit tricky because opcintype might be a polymorphic
6454                          * type such as ANYARRAY or ANYENUM; so what we have to test is
6455                          * whether the two actual column types can be concurrently cast to
6456                          * that type.  (Otherwise, we'd fail to reject combinations such
6457                          * as int[] and point[].)
6458                          */
6459                         Oid                     input_typeids[2];
6460                         Oid                     target_typeids[2];
6461
6462                         input_typeids[0] = pktype;
6463                         input_typeids[1] = fktype;
6464                         target_typeids[0] = opcintype;
6465                         target_typeids[1] = opcintype;
6466                         if (can_coerce_type(2, input_typeids, target_typeids,
6467                                                                 COERCION_IMPLICIT))
6468                         {
6469                                 pfeqop = ffeqop = ppeqop;
6470                                 pfeqop_right = opcintype;
6471                         }
6472                 }
6473
6474                 if (!(OidIsValid(pfeqop) && OidIsValid(ffeqop)))
6475                         ereport(ERROR,
6476                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
6477                                          errmsg("foreign key constraint \"%s\" "
6478                                                         "cannot be implemented",
6479                                                         fkconstraint->conname),
6480                                          errdetail("Key columns \"%s\" and \"%s\" "
6481                                                            "are of incompatible types: %s and %s.",
6482                                                            strVal(list_nth(fkconstraint->fk_attrs, i)),
6483                                                            strVal(list_nth(fkconstraint->pk_attrs, i)),
6484                                                            format_type_be(fktype),
6485                                                            format_type_be(pktype))));
6486
6487                 if (old_check_ok)
6488                 {
6489                         /*
6490                          * When a pfeqop changes, revalidate the constraint.  We could
6491                          * permit intra-opfamily changes, but that adds subtle complexity
6492                          * without any concrete benefit for core types.  We need not
6493                          * assess ppeqop or ffeqop, which RI_Initial_Check() does not use.
6494                          */
6495                         old_check_ok = (pfeqop == lfirst_oid(old_pfeqop_item));
6496                         old_pfeqop_item = lnext(old_pfeqop_item);
6497                 }
6498                 if (old_check_ok)
6499                 {
6500                         Oid                     old_fktype;
6501                         Oid                     new_fktype;
6502                         CoercionPathType old_pathtype;
6503                         CoercionPathType new_pathtype;
6504                         Oid                     old_castfunc;
6505                         Oid                     new_castfunc;
6506
6507                         /*
6508                          * Identify coercion pathways from each of the old and new FK-side
6509                          * column types to the right (foreign) operand type of the pfeqop.
6510                          * We may assume that pg_constraint.conkey is not changing.
6511                          */
6512                         old_fktype = tab->oldDesc->attrs[fkattnum[i] - 1]->atttypid;
6513                         new_fktype = fktype;
6514                         old_pathtype = findFkeyCast(pfeqop_right, old_fktype,
6515                                                                                 &old_castfunc);
6516                         new_pathtype = findFkeyCast(pfeqop_right, new_fktype,
6517                                                                                 &new_castfunc);
6518
6519                         /*
6520                          * Upon a change to the cast from the FK column to its pfeqop
6521                          * operand, revalidate the constraint.  For this evaluation, a
6522                          * binary coercion cast is equivalent to no cast at all.  While
6523                          * type implementors should design implicit casts with an eye
6524                          * toward consistency of operations like equality, we cannot
6525                          * assume here that they have done so.
6526                          *
6527                          * A function with a polymorphic argument could change behavior
6528                          * arbitrarily in response to get_fn_expr_argtype().  Therefore,
6529                          * when the cast destination is polymorphic, we only avoid
6530                          * revalidation if the input type has not changed at all.  Given
6531                          * just the core data types and operator classes, this requirement
6532                          * prevents no would-be optimizations.
6533                          *
6534                          * If the cast converts from a base type to a domain thereon, then
6535                          * that domain type must be the opcintype of the unique index.
6536                          * Necessarily, the primary key column must then be of the domain
6537                          * type.  Since the constraint was previously valid, all values on
6538                          * the foreign side necessarily exist on the primary side and in
6539                          * turn conform to the domain.  Consequently, we need not treat
6540                          * domains specially here.
6541                          *
6542                          * Since we require that all collations share the same notion of
6543                          * equality (which they do, because texteq reduces to bitwise
6544                          * equality), we don't compare collation here.
6545                          *
6546                          * We need not directly consider the PK type.  It's necessarily
6547                          * binary coercible to the opcintype of the unique index column,
6548                          * and ri_triggers.c will only deal with PK datums in terms of
6549                          * that opcintype.  Changing the opcintype also changes pfeqop.
6550                          */
6551                         old_check_ok = (new_pathtype == old_pathtype &&
6552                                                         new_castfunc == old_castfunc &&
6553                                                         (!IsPolymorphicType(pfeqop_right) ||
6554                                                          new_fktype == old_fktype));
6555
6556                 }
6557
6558                 pfeqoperators[i] = pfeqop;
6559                 ppeqoperators[i] = ppeqop;
6560                 ffeqoperators[i] = ffeqop;
6561         }
6562
6563         /*
6564          * Record the FK constraint in pg_constraint.
6565          */
6566         constrOid = CreateConstraintEntry(fkconstraint->conname,
6567                                                                           RelationGetNamespace(rel),
6568                                                                           CONSTRAINT_FOREIGN,
6569                                                                           fkconstraint->deferrable,
6570                                                                           fkconstraint->initdeferred,
6571                                                                           fkconstraint->initially_valid,
6572                                                                           RelationGetRelid(rel),
6573                                                                           fkattnum,
6574                                                                           numfks,
6575                                                                           InvalidOid,           /* not a domain
6576                                                                                                                  * constraint */
6577                                                                           indexOid,
6578                                                                           RelationGetRelid(pkrel),
6579                                                                           pkattnum,
6580                                                                           pfeqoperators,
6581                                                                           ppeqoperators,
6582                                                                           ffeqoperators,
6583                                                                           numpks,
6584                                                                           fkconstraint->fk_upd_action,
6585                                                                           fkconstraint->fk_del_action,
6586                                                                           fkconstraint->fk_matchtype,
6587                                                                           NULL,         /* no exclusion constraint */
6588                                                                           NULL,         /* no check constraint */
6589                                                                           NULL,
6590                                                                           NULL,
6591                                                                           true,         /* islocal */
6592                                                                           0,            /* inhcount */
6593                                                                           true,         /* isnoinherit */
6594                                                                           false);       /* is_internal */
6595         ObjectAddressSet(address, ConstraintRelationId, constrOid);
6596
6597         /*
6598          * Create the triggers that will enforce the constraint.
6599          */
6600         createForeignKeyTriggers(rel, RelationGetRelid(pkrel), fkconstraint,
6601                                                          constrOid, indexOid);
6602
6603         /*
6604          * Tell Phase 3 to check that the constraint is satisfied by existing
6605          * rows. We can skip this during table creation, when requested explicitly
6606          * by specifying NOT VALID in an ADD FOREIGN KEY command, and when we're
6607          * recreating a constraint following a SET DATA TYPE operation that did
6608          * not impugn its validity.
6609          */
6610         if (!old_check_ok && !fkconstraint->skip_validation)
6611         {
6612                 NewConstraint *newcon;
6613
6614                 newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
6615                 newcon->name = fkconstraint->conname;
6616                 newcon->contype = CONSTR_FOREIGN;
6617                 newcon->refrelid = RelationGetRelid(pkrel);
6618                 newcon->refindid = indexOid;
6619                 newcon->conid = constrOid;
6620                 newcon->qual = (Node *) fkconstraint;
6621
6622                 tab->constraints = lappend(tab->constraints, newcon);
6623         }
6624
6625         /*
6626          * Close pk table, but keep lock until we've committed.
6627          */
6628         heap_close(pkrel, NoLock);
6629
6630         return address;
6631 }
6632
6633 /*
6634  * ALTER TABLE ALTER CONSTRAINT
6635  *
6636  * Update the attributes of a constraint.
6637  *
6638  * Currently only works for Foreign Key constraints.
6639  * Foreign keys do not inherit, so we purposely ignore the
6640  * recursion bit here, but we keep the API the same for when
6641  * other constraint types are supported.
6642  *
6643  * If the constraint is modified, returns its address; otherwise, return
6644  * InvalidObjectAddress.
6645  */
6646 static ObjectAddress
6647 ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
6648                                           bool recurse, bool recursing, LOCKMODE lockmode)
6649 {
6650         Constraint *cmdcon;
6651         Relation        conrel;
6652         SysScanDesc scan;
6653         ScanKeyData key;
6654         HeapTuple       contuple;
6655         Form_pg_constraint currcon = NULL;
6656         bool            found = false;
6657         ObjectAddress address;
6658
6659         Assert(IsA(cmd->def, Constraint));
6660         cmdcon = (Constraint *) cmd->def;
6661
6662         conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
6663
6664         /*
6665          * Find and check the target constraint
6666          */
6667         ScanKeyInit(&key,
6668                                 Anum_pg_constraint_conrelid,
6669                                 BTEqualStrategyNumber, F_OIDEQ,
6670                                 ObjectIdGetDatum(RelationGetRelid(rel)));
6671         scan = systable_beginscan(conrel, ConstraintRelidIndexId,
6672                                                           true, NULL, 1, &key);
6673
6674         while (HeapTupleIsValid(contuple = systable_getnext(scan)))
6675         {
6676                 currcon = (Form_pg_constraint) GETSTRUCT(contuple);
6677                 if (strcmp(NameStr(currcon->conname), cmdcon->conname) == 0)
6678                 {
6679                         found = true;
6680                         break;
6681                 }
6682         }
6683
6684         if (!found)
6685                 ereport(ERROR,
6686                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
6687                                  errmsg("constraint \"%s\" of relation \"%s\" does not exist",
6688                                                 cmdcon->conname, RelationGetRelationName(rel))));
6689
6690         if (currcon->contype != CONSTRAINT_FOREIGN)
6691                 ereport(ERROR,
6692                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
6693                                  errmsg("constraint \"%s\" of relation \"%s\" is not a foreign key constraint",
6694                                                 cmdcon->conname, RelationGetRelationName(rel))));
6695
6696         if (currcon->condeferrable != cmdcon->deferrable ||
6697                 currcon->condeferred != cmdcon->initdeferred)
6698         {
6699                 HeapTuple       copyTuple;
6700                 HeapTuple       tgtuple;
6701                 Form_pg_constraint copy_con;
6702                 List       *otherrelids = NIL;
6703                 ScanKeyData tgkey;
6704                 SysScanDesc tgscan;
6705                 Relation        tgrel;
6706                 ListCell   *lc;
6707
6708                 /*
6709                  * Now update the catalog, while we have the door open.
6710                  */
6711                 copyTuple = heap_copytuple(contuple);
6712                 copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
6713                 copy_con->condeferrable = cmdcon->deferrable;
6714                 copy_con->condeferred = cmdcon->initdeferred;
6715                 simple_heap_update(conrel, &copyTuple->t_self, copyTuple);
6716                 CatalogUpdateIndexes(conrel, copyTuple);
6717
6718                 InvokeObjectPostAlterHook(ConstraintRelationId,
6719                                                                   HeapTupleGetOid(contuple), 0);
6720
6721                 heap_freetuple(copyTuple);
6722
6723                 /*
6724                  * Now we need to update the multiple entries in pg_trigger that
6725                  * implement the constraint.
6726                  */
6727                 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
6728
6729                 ScanKeyInit(&tgkey,
6730                                         Anum_pg_trigger_tgconstraint,
6731                                         BTEqualStrategyNumber, F_OIDEQ,
6732                                         ObjectIdGetDatum(HeapTupleGetOid(contuple)));
6733
6734                 tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
6735                                                                         NULL, 1, &tgkey);
6736
6737                 while (HeapTupleIsValid(tgtuple = systable_getnext(tgscan)))
6738                 {
6739                         Form_pg_trigger copy_tg;
6740
6741                         copyTuple = heap_copytuple(tgtuple);
6742                         copy_tg = (Form_pg_trigger) GETSTRUCT(copyTuple);
6743
6744                         /* Remember OIDs of other relation(s) involved in FK constraint */
6745                         if (copy_tg->tgrelid != RelationGetRelid(rel))
6746                                 otherrelids = list_append_unique_oid(otherrelids,
6747                                                                                                          copy_tg->tgrelid);
6748
6749                         copy_tg->tgdeferrable = cmdcon->deferrable;
6750                         copy_tg->tginitdeferred = cmdcon->initdeferred;
6751                         simple_heap_update(tgrel, &copyTuple->t_self, copyTuple);
6752                         CatalogUpdateIndexes(tgrel, copyTuple);
6753
6754                         InvokeObjectPostAlterHook(TriggerRelationId,
6755                                                                           HeapTupleGetOid(tgtuple), 0);
6756
6757                         heap_freetuple(copyTuple);
6758                 }
6759
6760                 systable_endscan(tgscan);
6761
6762                 heap_close(tgrel, RowExclusiveLock);
6763
6764                 /*
6765                  * Invalidate relcache so that others see the new attributes.  We must
6766                  * inval both the named rel and any others having relevant triggers.
6767                  * (At present there should always be exactly one other rel, but
6768                  * there's no need to hard-wire such an assumption here.)
6769                  */
6770                 CacheInvalidateRelcache(rel);
6771                 foreach(lc, otherrelids)
6772                 {
6773                         CacheInvalidateRelcacheByRelid(lfirst_oid(lc));
6774                 }
6775
6776                 ObjectAddressSet(address, ConstraintRelationId,
6777                                                  HeapTupleGetOid(contuple));
6778         }
6779         else
6780                 address = InvalidObjectAddress;
6781
6782         systable_endscan(scan);
6783
6784         heap_close(conrel, RowExclusiveLock);
6785
6786         return address;
6787 }
6788
6789 /*
6790  * ALTER TABLE VALIDATE CONSTRAINT
6791  *
6792  * XXX The reason we handle recursion here rather than at Phase 1 is because
6793  * there's no good way to skip recursing when handling foreign keys: there is
6794  * no need to lock children in that case, yet we wouldn't be able to avoid
6795  * doing so at that level.
6796  *
6797  * Return value is the address of the validated constraint.  If the constraint
6798  * was already validated, InvalidObjectAddress is returned.
6799  */
6800 static ObjectAddress
6801 ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
6802                                                  bool recursing, LOCKMODE lockmode)
6803 {
6804         Relation        conrel;
6805         SysScanDesc scan;
6806         ScanKeyData key;
6807         HeapTuple       tuple;
6808         Form_pg_constraint con = NULL;
6809         bool            found = false;
6810         ObjectAddress address;
6811
6812         conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
6813
6814         /*
6815          * Find and check the target constraint
6816          */
6817         ScanKeyInit(&key,
6818                                 Anum_pg_constraint_conrelid,
6819                                 BTEqualStrategyNumber, F_OIDEQ,
6820                                 ObjectIdGetDatum(RelationGetRelid(rel)));
6821         scan = systable_beginscan(conrel, ConstraintRelidIndexId,
6822                                                           true, NULL, 1, &key);
6823
6824         while (HeapTupleIsValid(tuple = systable_getnext(scan)))
6825         {
6826                 con = (Form_pg_constraint) GETSTRUCT(tuple);
6827                 if (strcmp(NameStr(con->conname), constrName) == 0)
6828                 {
6829                         found = true;
6830                         break;
6831                 }
6832         }
6833
6834         if (!found)
6835                 ereport(ERROR,
6836                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
6837                                  errmsg("constraint \"%s\" of relation \"%s\" does not exist",
6838                                                 constrName, RelationGetRelationName(rel))));
6839
6840         if (con->contype != CONSTRAINT_FOREIGN &&
6841                 con->contype != CONSTRAINT_CHECK)
6842                 ereport(ERROR,
6843                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
6844                                  errmsg("constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint",
6845                                                 constrName, RelationGetRelationName(rel))));
6846
6847         if (!con->convalidated)
6848         {
6849                 HeapTuple       copyTuple;
6850                 Form_pg_constraint copy_con;
6851
6852                 if (con->contype == CONSTRAINT_FOREIGN)
6853                 {
6854                         Relation        refrel;
6855
6856                         /*
6857                          * Triggers are already in place on both tables, so a concurrent
6858                          * write that alters the result here is not possible. Normally we
6859                          * can run a query here to do the validation, which would only
6860                          * require AccessShareLock. In some cases, it is possible that we
6861                          * might need to fire triggers to perform the check, so we take a
6862                          * lock at RowShareLock level just in case.
6863                          */
6864                         refrel = heap_open(con->confrelid, RowShareLock);
6865
6866                         validateForeignKeyConstraint(constrName, rel, refrel,
6867                                                                                  con->conindid,
6868                                                                                  HeapTupleGetOid(tuple));
6869                         heap_close(refrel, NoLock);
6870
6871                         /*
6872                          * Foreign keys do not inherit, so we purposely ignore the
6873                          * recursion bit here
6874                          */
6875                 }
6876                 else if (con->contype == CONSTRAINT_CHECK)
6877                 {
6878                         List       *children = NIL;
6879                         ListCell   *child;
6880
6881                         /*
6882                          * If we're recursing, the parent has already done this, so skip
6883                          * it.
6884                          */
6885                         if (!recursing)
6886                                 children = find_all_inheritors(RelationGetRelid(rel),
6887                                                                                            lockmode, NULL);
6888
6889                         /*
6890                          * For CHECK constraints, we must ensure that we only mark the
6891                          * constraint as validated on the parent if it's already validated
6892                          * on the children.
6893                          *
6894                          * We recurse before validating on the parent, to reduce risk of
6895                          * deadlocks.
6896                          */
6897                         foreach(child, children)
6898                         {
6899                                 Oid                     childoid = lfirst_oid(child);
6900                                 Relation        childrel;
6901
6902                                 if (childoid == RelationGetRelid(rel))
6903                                         continue;
6904
6905                                 /*
6906                                  * If we are told not to recurse, there had better not be any
6907                                  * child tables; else the addition would put them out of step.
6908                                  */
6909                                 if (!recurse)
6910                                         ereport(ERROR,
6911                                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
6912                                                          errmsg("constraint must be validated on child tables too")));
6913
6914                                 /* find_all_inheritors already got lock */
6915                                 childrel = heap_open(childoid, NoLock);
6916
6917                                 ATExecValidateConstraint(childrel, constrName, false,
6918                                                                                  true, lockmode);
6919                                 heap_close(childrel, NoLock);
6920                         }
6921
6922                         validateCheckConstraint(rel, tuple);
6923
6924                         /*
6925                          * Invalidate relcache so that others see the new validated
6926                          * constraint.
6927                          */
6928                         CacheInvalidateRelcache(rel);
6929                 }
6930
6931                 /*
6932                  * Now update the catalog, while we have the door open.
6933                  */
6934                 copyTuple = heap_copytuple(tuple);
6935                 copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
6936                 copy_con->convalidated = true;
6937                 simple_heap_update(conrel, &copyTuple->t_self, copyTuple);
6938                 CatalogUpdateIndexes(conrel, copyTuple);
6939
6940                 InvokeObjectPostAlterHook(ConstraintRelationId,
6941                                                                   HeapTupleGetOid(tuple), 0);
6942
6943                 heap_freetuple(copyTuple);
6944
6945                 ObjectAddressSet(address, ConstraintRelationId,
6946                                                  HeapTupleGetOid(tuple));
6947         }
6948         else
6949                 address = InvalidObjectAddress; /* already validated */
6950
6951         systable_endscan(scan);
6952
6953         heap_close(conrel, RowExclusiveLock);
6954
6955         return address;
6956 }
6957
6958
6959 /*
6960  * transformColumnNameList - transform list of column names
6961  *
6962  * Lookup each name and return its attnum and type OID
6963  */
6964 static int
6965 transformColumnNameList(Oid relId, List *colList,
6966                                                 int16 *attnums, Oid *atttypids)
6967 {
6968         ListCell   *l;
6969         int                     attnum;
6970
6971         attnum = 0;
6972         foreach(l, colList)
6973         {
6974                 char       *attname = strVal(lfirst(l));
6975                 HeapTuple       atttuple;
6976
6977                 atttuple = SearchSysCacheAttName(relId, attname);
6978                 if (!HeapTupleIsValid(atttuple))
6979                         ereport(ERROR,
6980                                         (errcode(ERRCODE_UNDEFINED_COLUMN),
6981                                          errmsg("column \"%s\" referenced in foreign key constraint does not exist",
6982                                                         attname)));
6983                 if (attnum >= INDEX_MAX_KEYS)
6984                         ereport(ERROR,
6985                                         (errcode(ERRCODE_TOO_MANY_COLUMNS),
6986                                          errmsg("cannot have more than %d keys in a foreign key",
6987                                                         INDEX_MAX_KEYS)));
6988                 attnums[attnum] = ((Form_pg_attribute) GETSTRUCT(atttuple))->attnum;
6989                 atttypids[attnum] = ((Form_pg_attribute) GETSTRUCT(atttuple))->atttypid;
6990                 ReleaseSysCache(atttuple);
6991                 attnum++;
6992         }
6993
6994         return attnum;
6995 }
6996
6997 /*
6998  * transformFkeyGetPrimaryKey -
6999  *
7000  *      Look up the names, attnums, and types of the primary key attributes
7001  *      for the pkrel.  Also return the index OID and index opclasses of the
7002  *      index supporting the primary key.
7003  *
7004  *      All parameters except pkrel are output parameters.  Also, the function
7005  *      return value is the number of attributes in the primary key.
7006  *
7007  *      Used when the column list in the REFERENCES specification is omitted.
7008  */
7009 static int
7010 transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
7011                                                    List **attnamelist,
7012                                                    int16 *attnums, Oid *atttypids,
7013                                                    Oid *opclasses)
7014 {
7015         List       *indexoidlist;
7016         ListCell   *indexoidscan;
7017         HeapTuple       indexTuple = NULL;
7018         Form_pg_index indexStruct = NULL;
7019         Datum           indclassDatum;
7020         bool            isnull;
7021         oidvector  *indclass;
7022         int                     i;
7023
7024         /*
7025          * Get the list of index OIDs for the table from the relcache, and look up
7026          * each one in the pg_index syscache until we find one marked primary key
7027          * (hopefully there isn't more than one such).  Insist it's valid, too.
7028          */
7029         *indexOid = InvalidOid;
7030
7031         indexoidlist = RelationGetIndexList(pkrel);
7032
7033         foreach(indexoidscan, indexoidlist)
7034         {
7035                 Oid                     indexoid = lfirst_oid(indexoidscan);
7036
7037                 indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
7038                 if (!HeapTupleIsValid(indexTuple))
7039                         elog(ERROR, "cache lookup failed for index %u", indexoid);
7040                 indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
7041                 if (indexStruct->indisprimary && IndexIsValid(indexStruct))
7042                 {
7043                         /*
7044                          * Refuse to use a deferrable primary key.  This is per SQL spec,
7045                          * and there would be a lot of interesting semantic problems if we
7046                          * tried to allow it.
7047                          */
7048                         if (!indexStruct->indimmediate)
7049                                 ereport(ERROR,
7050                                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
7051                                                  errmsg("cannot use a deferrable primary key for referenced table \"%s\"",
7052                                                                 RelationGetRelationName(pkrel))));
7053
7054                         *indexOid = indexoid;
7055                         break;
7056                 }
7057                 ReleaseSysCache(indexTuple);
7058         }
7059
7060         list_free(indexoidlist);
7061
7062         /*
7063          * Check that we found it
7064          */
7065         if (!OidIsValid(*indexOid))
7066                 ereport(ERROR,
7067                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
7068                                  errmsg("there is no primary key for referenced table \"%s\"",
7069                                                 RelationGetRelationName(pkrel))));
7070
7071         /* Must get indclass the hard way */
7072         indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
7073                                                                         Anum_pg_index_indclass, &isnull);
7074         Assert(!isnull);
7075         indclass = (oidvector *) DatumGetPointer(indclassDatum);
7076
7077         /*
7078          * Now build the list of PK attributes from the indkey definition (we
7079          * assume a primary key cannot have expressional elements)
7080          */
7081         *attnamelist = NIL;
7082         for (i = 0; i < indexStruct->indnatts; i++)
7083         {
7084                 int                     pkattno = indexStruct->indkey.values[i];
7085
7086                 attnums[i] = pkattno;
7087                 atttypids[i] = attnumTypeId(pkrel, pkattno);
7088                 opclasses[i] = indclass->values[i];
7089                 *attnamelist = lappend(*attnamelist,
7090                            makeString(pstrdup(NameStr(*attnumAttName(pkrel, pkattno)))));
7091         }
7092
7093         ReleaseSysCache(indexTuple);
7094
7095         return i;
7096 }
7097
7098 /*
7099  * transformFkeyCheckAttrs -
7100  *
7101  *      Make sure that the attributes of a referenced table belong to a unique
7102  *      (or primary key) constraint.  Return the OID of the index supporting
7103  *      the constraint, as well as the opclasses associated with the index
7104  *      columns.
7105  */
7106 static Oid
7107 transformFkeyCheckAttrs(Relation pkrel,
7108                                                 int numattrs, int16 *attnums,
7109                                                 Oid *opclasses) /* output parameter */
7110 {
7111         Oid                     indexoid = InvalidOid;
7112         bool            found = false;
7113         bool            found_deferrable = false;
7114         List       *indexoidlist;
7115         ListCell   *indexoidscan;
7116         int                     i,
7117                                 j;
7118
7119         /*
7120          * Reject duplicate appearances of columns in the referenced-columns list.
7121          * Such a case is forbidden by the SQL standard, and even if we thought it
7122          * useful to allow it, there would be ambiguity about how to match the
7123          * list to unique indexes (in particular, it'd be unclear which index
7124          * opclass goes with which FK column).
7125          */
7126         for (i = 0; i < numattrs; i++)
7127         {
7128                 for (j = i + 1; j < numattrs; j++)
7129                 {
7130                         if (attnums[i] == attnums[j])
7131                                 ereport(ERROR,
7132                                                 (errcode(ERRCODE_INVALID_FOREIGN_KEY),
7133                                                  errmsg("foreign key referenced-columns list must not contain duplicates")));
7134                 }
7135         }
7136
7137         /*
7138          * Get the list of index OIDs for the table from the relcache, and look up
7139          * each one in the pg_index syscache, and match unique indexes to the list
7140          * of attnums we are given.
7141          */
7142         indexoidlist = RelationGetIndexList(pkrel);
7143
7144         foreach(indexoidscan, indexoidlist)
7145         {
7146                 HeapTuple       indexTuple;
7147                 Form_pg_index indexStruct;
7148
7149                 indexoid = lfirst_oid(indexoidscan);
7150                 indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
7151                 if (!HeapTupleIsValid(indexTuple))
7152                         elog(ERROR, "cache lookup failed for index %u", indexoid);
7153                 indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
7154
7155                 /*
7156                  * Must have the right number of columns; must be unique and not a
7157                  * partial index; forget it if there are any expressions, too. Invalid
7158                  * indexes are out as well.
7159                  */
7160                 if (indexStruct->indnatts == numattrs &&
7161                         indexStruct->indisunique &&
7162                         IndexIsValid(indexStruct) &&
7163                         heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
7164                         heap_attisnull(indexTuple, Anum_pg_index_indexprs))
7165                 {
7166                         Datum           indclassDatum;
7167                         bool            isnull;
7168                         oidvector  *indclass;
7169
7170                         /* Must get indclass the hard way */
7171                         indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
7172                                                                                         Anum_pg_index_indclass, &isnull);
7173                         Assert(!isnull);
7174                         indclass = (oidvector *) DatumGetPointer(indclassDatum);
7175
7176                         /*
7177                          * The given attnum list may match the index columns in any order.
7178                          * Check for a match, and extract the appropriate opclasses while
7179                          * we're at it.
7180                          *
7181                          * We know that attnums[] is duplicate-free per the test at the
7182                          * start of this function, and we checked above that the number of
7183                          * index columns agrees, so if we find a match for each attnums[]
7184                          * entry then we must have a one-to-one match in some order.
7185                          */
7186                         for (i = 0; i < numattrs; i++)
7187                         {
7188                                 found = false;
7189                                 for (j = 0; j < numattrs; j++)
7190                                 {
7191                                         if (attnums[i] == indexStruct->indkey.values[j])
7192                                         {
7193                                                 opclasses[i] = indclass->values[j];
7194                                                 found = true;
7195                                                 break;
7196                                         }
7197                                 }
7198                                 if (!found)
7199                                         break;
7200                         }
7201
7202                         /*
7203                          * Refuse to use a deferrable unique/primary key.  This is per SQL
7204                          * spec, and there would be a lot of interesting semantic problems
7205                          * if we tried to allow it.
7206                          */
7207                         if (found && !indexStruct->indimmediate)
7208                         {
7209                                 /*
7210                                  * Remember that we found an otherwise matching index, so that
7211                                  * we can generate a more appropriate error message.
7212                                  */
7213                                 found_deferrable = true;
7214                                 found = false;
7215                         }
7216                 }
7217                 ReleaseSysCache(indexTuple);
7218                 if (found)
7219                         break;
7220         }
7221
7222         if (!found)
7223         {
7224                 if (found_deferrable)
7225                         ereport(ERROR,
7226                                         (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
7227                                          errmsg("cannot use a deferrable unique constraint for referenced table \"%s\"",
7228                                                         RelationGetRelationName(pkrel))));
7229                 else
7230                         ereport(ERROR,
7231                                         (errcode(ERRCODE_INVALID_FOREIGN_KEY),
7232                                          errmsg("there is no unique constraint matching given keys for referenced table \"%s\"",
7233                                                         RelationGetRelationName(pkrel))));
7234         }
7235
7236         list_free(indexoidlist);
7237
7238         return indexoid;
7239 }
7240
7241 /*
7242  * findFkeyCast -
7243  *
7244  *      Wrapper around find_coercion_pathway() for ATAddForeignKeyConstraint().
7245  *      Caller has equal regard for binary coercibility and for an exact match.
7246 */
7247 static CoercionPathType
7248 findFkeyCast(Oid targetTypeId, Oid sourceTypeId, Oid *funcid)
7249 {
7250         CoercionPathType ret;
7251
7252         if (targetTypeId == sourceTypeId)
7253         {
7254                 ret = COERCION_PATH_RELABELTYPE;
7255                 *funcid = InvalidOid;
7256         }
7257         else
7258         {
7259                 ret = find_coercion_pathway(targetTypeId, sourceTypeId,
7260                                                                         COERCION_IMPLICIT, funcid);
7261                 if (ret == COERCION_PATH_NONE)
7262                         /* A previously-relied-upon cast is now gone. */
7263                         elog(ERROR, "could not find cast from %u to %u",
7264                                  sourceTypeId, targetTypeId);
7265         }
7266
7267         return ret;
7268 }
7269
7270 /* Permissions checks for ADD FOREIGN KEY */
7271 static void
7272 checkFkeyPermissions(Relation rel, int16 *attnums, int natts)
7273 {
7274         Oid                     roleid = GetUserId();
7275         AclResult       aclresult;
7276         int                     i;
7277
7278         /* Okay if we have relation-level REFERENCES permission */
7279         aclresult = pg_class_aclcheck(RelationGetRelid(rel), roleid,
7280                                                                   ACL_REFERENCES);
7281         if (aclresult == ACLCHECK_OK)
7282                 return;
7283         /* Else we must have REFERENCES on each column */
7284         for (i = 0; i < natts; i++)
7285         {
7286                 aclresult = pg_attribute_aclcheck(RelationGetRelid(rel), attnums[i],
7287                                                                                   roleid, ACL_REFERENCES);
7288                 if (aclresult != ACLCHECK_OK)
7289                         aclcheck_error(aclresult, ACL_KIND_CLASS,
7290                                                    RelationGetRelationName(rel));
7291         }
7292 }
7293
7294 /*
7295  * Scan the existing rows in a table to verify they meet a proposed
7296  * CHECK constraint.
7297  *
7298  * The caller must have opened and locked the relation appropriately.
7299  */
7300 static void
7301 validateCheckConstraint(Relation rel, HeapTuple constrtup)
7302 {
7303         EState     *estate;
7304         Datum           val;
7305         char       *conbin;
7306         Expr       *origexpr;
7307         List       *exprstate;
7308         TupleDesc       tupdesc;
7309         HeapScanDesc scan;
7310         HeapTuple       tuple;
7311         ExprContext *econtext;
7312         MemoryContext oldcxt;
7313         TupleTableSlot *slot;
7314         Form_pg_constraint constrForm;
7315         bool            isnull;
7316         Snapshot        snapshot;
7317
7318         /* VALIDATE CONSTRAINT is a no-op for foreign tables */
7319         if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
7320                 return;
7321
7322         constrForm = (Form_pg_constraint) GETSTRUCT(constrtup);
7323
7324         estate = CreateExecutorState();
7325
7326         /*
7327          * XXX this tuple doesn't really come from a syscache, but this doesn't
7328          * matter to SysCacheGetAttr, because it only wants to be able to fetch
7329          * the tupdesc
7330          */
7331         val = SysCacheGetAttr(CONSTROID, constrtup, Anum_pg_constraint_conbin,
7332                                                   &isnull);
7333         if (isnull)
7334                 elog(ERROR, "null conbin for constraint %u",
7335                          HeapTupleGetOid(constrtup));
7336         conbin = TextDatumGetCString(val);
7337         origexpr = (Expr *) stringToNode(conbin);
7338         exprstate = (List *)
7339                 ExecPrepareExpr((Expr *) make_ands_implicit(origexpr), estate);
7340
7341         econtext = GetPerTupleExprContext(estate);
7342         tupdesc = RelationGetDescr(rel);
7343         slot = MakeSingleTupleTableSlot(tupdesc);
7344         econtext->ecxt_scantuple = slot;
7345
7346         snapshot = RegisterSnapshot(GetLatestSnapshot());
7347         scan = heap_beginscan(rel, snapshot, 0, NULL);
7348
7349         /*
7350          * Switch to per-tuple memory context and reset it for each tuple
7351          * produced, so we don't leak memory.
7352          */
7353         oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
7354
7355         while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
7356         {
7357                 ExecStoreTuple(tuple, slot, InvalidBuffer, false);
7358
7359                 if (!ExecQual(exprstate, econtext, true))
7360                         ereport(ERROR,
7361                                         (errcode(ERRCODE_CHECK_VIOLATION),
7362                                          errmsg("check constraint \"%s\" is violated by some row",
7363                                                         NameStr(constrForm->conname)),
7364                                          errtableconstraint(rel, NameStr(constrForm->conname))));
7365
7366                 ResetExprContext(econtext);
7367         }
7368
7369         MemoryContextSwitchTo(oldcxt);
7370         heap_endscan(scan);
7371         UnregisterSnapshot(snapshot);
7372         ExecDropSingleTupleTableSlot(slot);
7373         FreeExecutorState(estate);
7374 }
7375
7376 /*
7377  * Scan the existing rows in a table to verify they meet a proposed FK
7378  * constraint.
7379  *
7380  * Caller must have opened and locked both relations appropriately.
7381  */
7382 static void
7383 validateForeignKeyConstraint(char *conname,
7384                                                          Relation rel,
7385                                                          Relation pkrel,
7386                                                          Oid pkindOid,
7387                                                          Oid constraintOid)
7388 {
7389         HeapScanDesc scan;
7390         HeapTuple       tuple;
7391         Trigger         trig;
7392         Snapshot        snapshot;
7393
7394         ereport(DEBUG1,
7395                         (errmsg("validating foreign key constraint \"%s\"", conname)));
7396
7397         /*
7398          * Build a trigger call structure; we'll need it either way.
7399          */
7400         MemSet(&trig, 0, sizeof(trig));
7401         trig.tgoid = InvalidOid;
7402         trig.tgname = conname;
7403         trig.tgenabled = TRIGGER_FIRES_ON_ORIGIN;
7404         trig.tgisinternal = TRUE;
7405         trig.tgconstrrelid = RelationGetRelid(pkrel);
7406         trig.tgconstrindid = pkindOid;
7407         trig.tgconstraint = constraintOid;
7408         trig.tgdeferrable = FALSE;
7409         trig.tginitdeferred = FALSE;
7410         /* we needn't fill in tgargs or tgqual */
7411
7412         /*
7413          * See if we can do it with a single LEFT JOIN query.  A FALSE result
7414          * indicates we must proceed with the fire-the-trigger method.
7415          */
7416         if (RI_Initial_Check(&trig, rel, pkrel))
7417                 return;
7418
7419         /*
7420          * Scan through each tuple, calling RI_FKey_check_ins (insert trigger) as
7421          * if that tuple had just been inserted.  If any of those fail, it should
7422          * ereport(ERROR) and that's that.
7423          */
7424         snapshot = RegisterSnapshot(GetLatestSnapshot());
7425         scan = heap_beginscan(rel, snapshot, 0, NULL);
7426
7427         while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
7428         {
7429                 FunctionCallInfoData fcinfo;
7430                 TriggerData trigdata;
7431
7432                 /*
7433                  * Make a call to the trigger function
7434                  *
7435                  * No parameters are passed, but we do set a context
7436                  */
7437                 MemSet(&fcinfo, 0, sizeof(fcinfo));
7438
7439                 /*
7440                  * We assume RI_FKey_check_ins won't look at flinfo...
7441                  */
7442                 trigdata.type = T_TriggerData;
7443                 trigdata.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW;
7444                 trigdata.tg_relation = rel;
7445                 trigdata.tg_trigtuple = tuple;
7446                 trigdata.tg_newtuple = NULL;
7447                 trigdata.tg_trigger = &trig;
7448                 trigdata.tg_trigtuplebuf = scan->rs_cbuf;
7449                 trigdata.tg_newtuplebuf = InvalidBuffer;
7450
7451                 fcinfo.context = (Node *) &trigdata;
7452
7453                 RI_FKey_check_ins(&fcinfo);
7454         }
7455
7456         heap_endscan(scan);
7457         UnregisterSnapshot(snapshot);
7458 }
7459
7460 static void
7461 CreateFKCheckTrigger(Oid myRelOid, Oid refRelOid, Constraint *fkconstraint,
7462                                          Oid constraintOid, Oid indexOid, bool on_insert)
7463 {
7464         CreateTrigStmt *fk_trigger;
7465
7466         /*
7467          * Note: for a self-referential FK (referencing and referenced tables are
7468          * the same), it is important that the ON UPDATE action fires before the
7469          * CHECK action, since both triggers will fire on the same row during an
7470          * UPDATE event; otherwise the CHECK trigger will be checking a non-final
7471          * state of the row.  Triggers fire in name order, so we ensure this by
7472          * using names like "RI_ConstraintTrigger_a_NNNN" for the action triggers
7473          * and "RI_ConstraintTrigger_c_NNNN" for the check triggers.
7474          */
7475         fk_trigger = makeNode(CreateTrigStmt);
7476         fk_trigger->trigname = "RI_ConstraintTrigger_c";
7477         fk_trigger->relation = NULL;
7478         fk_trigger->row = true;
7479         fk_trigger->timing = TRIGGER_TYPE_AFTER;
7480
7481         /* Either ON INSERT or ON UPDATE */
7482         if (on_insert)
7483         {
7484                 fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins");
7485                 fk_trigger->events = TRIGGER_TYPE_INSERT;
7486         }
7487         else
7488         {
7489                 fk_trigger->funcname = SystemFuncName("RI_FKey_check_upd");
7490                 fk_trigger->events = TRIGGER_TYPE_UPDATE;
7491         }
7492
7493         fk_trigger->columns = NIL;
7494         fk_trigger->whenClause = NULL;
7495         fk_trigger->isconstraint = true;
7496         fk_trigger->deferrable = fkconstraint->deferrable;
7497         fk_trigger->initdeferred = fkconstraint->initdeferred;
7498         fk_trigger->constrrel = NULL;
7499         fk_trigger->args = NIL;
7500
7501         (void) CreateTrigger(fk_trigger, NULL, myRelOid, refRelOid, constraintOid,
7502                                                  indexOid, true);
7503
7504         /* Make changes-so-far visible */
7505         CommandCounterIncrement();
7506 }
7507
7508 /*
7509  * Create the triggers that implement an FK constraint.
7510  */
7511 static void
7512 createForeignKeyTriggers(Relation rel, Oid refRelOid, Constraint *fkconstraint,
7513                                                  Oid constraintOid, Oid indexOid)
7514 {
7515         Oid                     myRelOid;
7516         CreateTrigStmt *fk_trigger;
7517
7518         myRelOid = RelationGetRelid(rel);
7519
7520         /* Make changes-so-far visible */
7521         CommandCounterIncrement();
7522
7523         /*
7524          * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
7525          * DELETE action on the referenced table.
7526          */
7527         fk_trigger = makeNode(CreateTrigStmt);
7528         fk_trigger->trigname = "RI_ConstraintTrigger_a";
7529         fk_trigger->relation = NULL;
7530         fk_trigger->row = true;
7531         fk_trigger->timing = TRIGGER_TYPE_AFTER;
7532         fk_trigger->events = TRIGGER_TYPE_DELETE;
7533         fk_trigger->columns = NIL;
7534         fk_trigger->whenClause = NULL;
7535         fk_trigger->isconstraint = true;
7536         fk_trigger->constrrel = NULL;
7537         switch (fkconstraint->fk_del_action)
7538         {
7539                 case FKCONSTR_ACTION_NOACTION:
7540                         fk_trigger->deferrable = fkconstraint->deferrable;
7541                         fk_trigger->initdeferred = fkconstraint->initdeferred;
7542                         fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_del");
7543                         break;
7544                 case FKCONSTR_ACTION_RESTRICT:
7545                         fk_trigger->deferrable = false;
7546                         fk_trigger->initdeferred = false;
7547                         fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_del");
7548                         break;
7549                 case FKCONSTR_ACTION_CASCADE:
7550                         fk_trigger->deferrable = false;
7551                         fk_trigger->initdeferred = false;
7552                         fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_del");
7553                         break;
7554                 case FKCONSTR_ACTION_SETNULL:
7555                         fk_trigger->deferrable = false;
7556                         fk_trigger->initdeferred = false;
7557                         fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_del");
7558                         break;
7559                 case FKCONSTR_ACTION_SETDEFAULT:
7560                         fk_trigger->deferrable = false;
7561                         fk_trigger->initdeferred = false;
7562                         fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_del");
7563                         break;
7564                 default:
7565                         elog(ERROR, "unrecognized FK action type: %d",
7566                                  (int) fkconstraint->fk_del_action);
7567                         break;
7568         }
7569         fk_trigger->args = NIL;
7570
7571         (void) CreateTrigger(fk_trigger, NULL, refRelOid, myRelOid, constraintOid,
7572                                                  indexOid, true);
7573
7574         /* Make changes-so-far visible */
7575         CommandCounterIncrement();
7576
7577         /*
7578          * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
7579          * UPDATE action on the referenced table.
7580          */
7581         fk_trigger = makeNode(CreateTrigStmt);
7582         fk_trigger->trigname = "RI_ConstraintTrigger_a";
7583         fk_trigger->relation = NULL;
7584         fk_trigger->row = true;
7585         fk_trigger->timing = TRIGGER_TYPE_AFTER;
7586         fk_trigger->events = TRIGGER_TYPE_UPDATE;
7587         fk_trigger->columns = NIL;
7588         fk_trigger->whenClause = NULL;
7589         fk_trigger->isconstraint = true;
7590         fk_trigger->constrrel = NULL;
7591         switch (fkconstraint->fk_upd_action)
7592         {
7593                 case FKCONSTR_ACTION_NOACTION:
7594                         fk_trigger->deferrable = fkconstraint->deferrable;
7595                         fk_trigger->initdeferred = fkconstraint->initdeferred;
7596                         fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_upd");
7597                         break;
7598                 case FKCONSTR_ACTION_RESTRICT:
7599                         fk_trigger->deferrable = false;
7600                         fk_trigger->initdeferred = false;
7601                         fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_upd");
7602                         break;
7603                 case FKCONSTR_ACTION_CASCADE:
7604                         fk_trigger->deferrable = false;
7605                         fk_trigger->initdeferred = false;
7606                         fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_upd");
7607                         break;
7608                 case FKCONSTR_ACTION_SETNULL:
7609                         fk_trigger->deferrable = false;
7610                         fk_trigger->initdeferred = false;
7611                         fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_upd");
7612                         break;
7613                 case FKCONSTR_ACTION_SETDEFAULT:
7614                         fk_trigger->deferrable = false;
7615                         fk_trigger->initdeferred = false;
7616                         fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_upd");
7617                         break;
7618                 default:
7619                         elog(ERROR, "unrecognized FK action type: %d",
7620                                  (int) fkconstraint->fk_upd_action);
7621                         break;
7622         }
7623         fk_trigger->args = NIL;
7624
7625         (void) CreateTrigger(fk_trigger, NULL, refRelOid, myRelOid, constraintOid,
7626                                                  indexOid, true);
7627
7628         /* Make changes-so-far visible */
7629         CommandCounterIncrement();
7630
7631         /*
7632          * Build and execute CREATE CONSTRAINT TRIGGER statements for the CHECK
7633          * action for both INSERTs and UPDATEs on the referencing table.
7634          */
7635         CreateFKCheckTrigger(myRelOid, refRelOid, fkconstraint, constraintOid,
7636                                                  indexOid, true);
7637         CreateFKCheckTrigger(myRelOid, refRelOid, fkconstraint, constraintOid,
7638                                                  indexOid, false);
7639 }
7640
7641 /*
7642  * ALTER TABLE DROP CONSTRAINT
7643  *
7644  * Like DROP COLUMN, we can't use the normal ALTER TABLE recursion mechanism.
7645  */
7646 static void
7647 ATExecDropConstraint(Relation rel, const char *constrName,
7648                                          DropBehavior behavior,
7649                                          bool recurse, bool recursing,
7650                                          bool missing_ok, LOCKMODE lockmode)
7651 {
7652         List       *children;
7653         ListCell   *child;
7654         Relation        conrel;
7655         Form_pg_constraint con;
7656         SysScanDesc scan;
7657         ScanKeyData key;
7658         HeapTuple       tuple;
7659         bool            found = false;
7660         bool            is_no_inherit_constraint = false;
7661
7662         /* At top level, permission check was done in ATPrepCmd, else do it */
7663         if (recursing)
7664                 ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
7665
7666         conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
7667
7668         /*
7669          * Find and drop the target constraint
7670          */
7671         ScanKeyInit(&key,
7672                                 Anum_pg_constraint_conrelid,
7673                                 BTEqualStrategyNumber, F_OIDEQ,
7674                                 ObjectIdGetDatum(RelationGetRelid(rel)));
7675         scan = systable_beginscan(conrel, ConstraintRelidIndexId,
7676                                                           true, NULL, 1, &key);
7677
7678         while (HeapTupleIsValid(tuple = systable_getnext(scan)))
7679         {
7680                 ObjectAddress conobj;
7681
7682                 con = (Form_pg_constraint) GETSTRUCT(tuple);
7683
7684                 if (strcmp(NameStr(con->conname), constrName) != 0)
7685                         continue;
7686
7687                 /* Don't drop inherited constraints */
7688                 if (con->coninhcount > 0 && !recursing)
7689                         ereport(ERROR,
7690                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
7691                                          errmsg("cannot drop inherited constraint \"%s\" of relation \"%s\"",
7692                                                         constrName, RelationGetRelationName(rel))));
7693
7694                 is_no_inherit_constraint = con->connoinherit;
7695
7696                 /*
7697                  * Perform the actual constraint deletion
7698                  */
7699                 conobj.classId = ConstraintRelationId;
7700                 conobj.objectId = HeapTupleGetOid(tuple);
7701                 conobj.objectSubId = 0;
7702
7703                 performDeletion(&conobj, behavior, 0);
7704
7705                 found = true;
7706
7707                 /* constraint found and dropped -- no need to keep looping */
7708                 break;
7709         }
7710
7711         systable_endscan(scan);
7712
7713         if (!found)
7714         {
7715                 if (!missing_ok)
7716                 {
7717                         ereport(ERROR,
7718                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
7719                                 errmsg("constraint \"%s\" of relation \"%s\" does not exist",
7720                                            constrName, RelationGetRelationName(rel))));
7721                 }
7722                 else
7723                 {
7724                         ereport(NOTICE,
7725                                         (errmsg("constraint \"%s\" of relation \"%s\" does not exist, skipping",
7726                                                         constrName, RelationGetRelationName(rel))));
7727                         heap_close(conrel, RowExclusiveLock);
7728                         return;
7729                 }
7730         }
7731
7732         /*
7733          * Propagate to children as appropriate.  Unlike most other ALTER
7734          * routines, we have to do this one level of recursion at a time; we can't
7735          * use find_all_inheritors to do it in one pass.
7736          */
7737         if (!is_no_inherit_constraint)
7738                 children = find_inheritance_children(RelationGetRelid(rel), lockmode);
7739         else
7740                 children = NIL;
7741
7742         foreach(child, children)
7743         {
7744                 Oid                     childrelid = lfirst_oid(child);
7745                 Relation        childrel;
7746                 HeapTuple       copy_tuple;
7747
7748                 /* find_inheritance_children already got lock */
7749                 childrel = heap_open(childrelid, NoLock);
7750                 CheckTableNotInUse(childrel, "ALTER TABLE");
7751
7752                 ScanKeyInit(&key,
7753                                         Anum_pg_constraint_conrelid,
7754                                         BTEqualStrategyNumber, F_OIDEQ,
7755                                         ObjectIdGetDatum(childrelid));
7756                 scan = systable_beginscan(conrel, ConstraintRelidIndexId,
7757                                                                   true, NULL, 1, &key);
7758
7759                 /* scan for matching tuple - there should only be one */
7760                 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
7761                 {
7762                         con = (Form_pg_constraint) GETSTRUCT(tuple);
7763
7764                         /* Right now only CHECK constraints can be inherited */
7765                         if (con->contype != CONSTRAINT_CHECK)
7766                                 continue;
7767
7768                         if (strcmp(NameStr(con->conname), constrName) == 0)
7769                                 break;
7770                 }
7771
7772                 if (!HeapTupleIsValid(tuple))
7773                         ereport(ERROR,
7774                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
7775                                 errmsg("constraint \"%s\" of relation \"%s\" does not exist",
7776                                            constrName,
7777                                            RelationGetRelationName(childrel))));
7778
7779                 copy_tuple = heap_copytuple(tuple);
7780
7781                 systable_endscan(scan);
7782
7783                 con = (Form_pg_constraint) GETSTRUCT(copy_tuple);
7784
7785                 if (con->coninhcount <= 0)              /* shouldn't happen */
7786                         elog(ERROR, "relation %u has non-inherited constraint \"%s\"",
7787                                  childrelid, constrName);
7788
7789                 if (recurse)
7790                 {
7791                         /*
7792                          * If the child constraint has other definition sources, just
7793                          * decrement its inheritance count; if not, recurse to delete it.
7794                          */
7795                         if (con->coninhcount == 1 && !con->conislocal)
7796                         {
7797                                 /* Time to delete this child constraint, too */
7798                                 ATExecDropConstraint(childrel, constrName, behavior,
7799                                                                          true, true,
7800                                                                          false, lockmode);
7801                         }
7802                         else
7803                         {
7804                                 /* Child constraint must survive my deletion */
7805                                 con->coninhcount--;
7806                                 simple_heap_update(conrel, &copy_tuple->t_self, copy_tuple);
7807                                 CatalogUpdateIndexes(conrel, copy_tuple);
7808
7809                                 /* Make update visible */
7810                                 CommandCounterIncrement();
7811                         }
7812                 }
7813                 else
7814                 {
7815                         /*
7816                          * If we were told to drop ONLY in this table (no recursion), we
7817                          * need to mark the inheritors' constraints as locally defined
7818                          * rather than inherited.
7819                          */
7820                         con->coninhcount--;
7821                         con->conislocal = true;
7822
7823                         simple_heap_update(conrel, &copy_tuple->t_self, copy_tuple);
7824                         CatalogUpdateIndexes(conrel, copy_tuple);
7825
7826                         /* Make update visible */
7827                         CommandCounterIncrement();
7828                 }
7829
7830                 heap_freetuple(copy_tuple);
7831
7832                 heap_close(childrel, NoLock);
7833         }
7834
7835         heap_close(conrel, RowExclusiveLock);
7836 }
7837
7838 /*
7839  * ALTER COLUMN TYPE
7840  */
7841 static void
7842 ATPrepAlterColumnType(List **wqueue,
7843                                           AlteredTableInfo *tab, Relation rel,
7844                                           bool recurse, bool recursing,
7845                                           AlterTableCmd *cmd, LOCKMODE lockmode)
7846 {
7847         char       *colName = cmd->name;
7848         ColumnDef  *def = (ColumnDef *) cmd->def;
7849         TypeName   *typeName = def->typeName;
7850         Node       *transform = def->cooked_default;
7851         HeapTuple       tuple;
7852         Form_pg_attribute attTup;
7853         AttrNumber      attnum;
7854         Oid                     targettype;
7855         int32           targettypmod;
7856         Oid                     targetcollid;
7857         NewColumnValue *newval;
7858         ParseState *pstate = make_parsestate(NULL);
7859         AclResult       aclresult;
7860
7861         if (rel->rd_rel->reloftype && !recursing)
7862                 ereport(ERROR,
7863                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
7864                                  errmsg("cannot alter column type of typed table")));
7865
7866         /* lookup the attribute so we can check inheritance status */
7867         tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
7868         if (!HeapTupleIsValid(tuple))
7869                 ereport(ERROR,
7870                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
7871                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
7872                                                 colName, RelationGetRelationName(rel))));
7873         attTup = (Form_pg_attribute) GETSTRUCT(tuple);
7874         attnum = attTup->attnum;
7875
7876         /* Can't alter a system attribute */
7877         if (attnum <= 0)
7878                 ereport(ERROR,
7879                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
7880                                  errmsg("cannot alter system column \"%s\"",
7881                                                 colName)));
7882
7883         /* Don't alter inherited columns */
7884         if (attTup->attinhcount > 0 && !recursing)
7885                 ereport(ERROR,
7886                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
7887                                  errmsg("cannot alter inherited column \"%s\"",
7888                                                 colName)));
7889
7890         /* Look up the target type */
7891         typenameTypeIdAndMod(NULL, typeName, &targettype, &targettypmod);
7892
7893         aclresult = pg_type_aclcheck(targettype, GetUserId(), ACL_USAGE);
7894         if (aclresult != ACLCHECK_OK)
7895                 aclcheck_error_type(aclresult, targettype);
7896
7897         /* And the collation */
7898         targetcollid = GetColumnDefCollation(NULL, def, targettype);
7899
7900         /* make sure datatype is legal for a column */
7901         CheckAttributeType(colName, targettype, targetcollid,
7902                                            list_make1_oid(rel->rd_rel->reltype),
7903                                            false);
7904
7905         if (tab->relkind == RELKIND_RELATION)
7906         {
7907                 /*
7908                  * Set up an expression to transform the old data value to the new
7909                  * type. If a USING option was given, use the expression as
7910                  * transformed by transformAlterTableStmt, else just take the old
7911                  * value and try to coerce it.  We do this first so that type
7912                  * incompatibility can be detected before we waste effort, and because
7913                  * we need the expression to be parsed against the original table row
7914                  * type.
7915                  */
7916                 if (!transform)
7917                 {
7918                         transform = (Node *) makeVar(1, attnum,
7919                                                                                  attTup->atttypid, attTup->atttypmod,
7920                                                                                  attTup->attcollation,
7921                                                                                  0);
7922                 }
7923
7924                 transform = coerce_to_target_type(pstate,
7925                                                                                   transform, exprType(transform),
7926                                                                                   targettype, targettypmod,
7927                                                                                   COERCION_ASSIGNMENT,
7928                                                                                   COERCE_IMPLICIT_CAST,
7929                                                                                   -1);
7930                 if (transform == NULL)
7931                 {
7932                         /* error text depends on whether USING was specified or not */
7933                         if (def->cooked_default != NULL)
7934                                 ereport(ERROR,
7935                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
7936                                                  errmsg("result of USING clause for column \"%s\""
7937                                                                 " cannot be cast automatically to type %s",
7938                                                                 colName, format_type_be(targettype)),
7939                                                  errhint("You might need to add an explicit cast.")));
7940                         else
7941                                 ereport(ERROR,
7942                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
7943                                                  errmsg("column \"%s\" cannot be cast automatically to type %s",
7944                                                                 colName, format_type_be(targettype)),
7945                                 /* translator: USING is SQL, don't translate it */
7946                                            errhint("You might need to specify \"USING %s::%s\".",
7947                                                            quote_identifier(colName),
7948                                                            format_type_with_typemod(targettype,
7949                                                                                                                 targettypmod))));
7950                 }
7951
7952                 /* Fix collations after all else */
7953                 assign_expr_collations(pstate, transform);
7954
7955                 /* Plan the expr now so we can accurately assess the need to rewrite. */
7956                 transform = (Node *) expression_planner((Expr *) transform);
7957
7958                 /*
7959                  * Add a work queue item to make ATRewriteTable update the column
7960                  * contents.
7961                  */
7962                 newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
7963                 newval->attnum = attnum;
7964                 newval->expr = (Expr *) transform;
7965
7966                 tab->newvals = lappend(tab->newvals, newval);
7967                 if (ATColumnChangeRequiresRewrite(transform, attnum))
7968                         tab->rewrite |= AT_REWRITE_COLUMN_REWRITE;
7969         }
7970         else if (transform)
7971                 ereport(ERROR,
7972                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
7973                                  errmsg("\"%s\" is not a table",
7974                                                 RelationGetRelationName(rel))));
7975
7976         if (tab->relkind == RELKIND_COMPOSITE_TYPE ||
7977                 tab->relkind == RELKIND_FOREIGN_TABLE)
7978         {
7979                 /*
7980                  * For composite types, do this check now.  Tables will check it later
7981                  * when the table is being rewritten.
7982                  */
7983                 find_composite_type_dependencies(rel->rd_rel->reltype, rel, NULL);
7984         }
7985
7986         ReleaseSysCache(tuple);
7987
7988         /*
7989          * The recursion case is handled by ATSimpleRecursion.  However, if we are
7990          * told not to recurse, there had better not be any child tables; else the
7991          * alter would put them out of step.
7992          */
7993         if (recurse)
7994                 ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
7995         else if (!recursing &&
7996                          find_inheritance_children(RelationGetRelid(rel), NoLock) != NIL)
7997                 ereport(ERROR,
7998                                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
7999                                  errmsg("type of inherited column \"%s\" must be changed in child tables too",
8000                                                 colName)));
8001
8002         if (tab->relkind == RELKIND_COMPOSITE_TYPE)
8003                 ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
8004 }
8005
8006 /*
8007  * When the data type of a column is changed, a rewrite might not be required
8008  * if the new type is sufficiently identical to the old one, and the USING
8009  * clause isn't trying to insert some other value.  It's safe to skip the
8010  * rewrite if the old type is binary coercible to the new type, or if the
8011  * new type is an unconstrained domain over the old type.  In the case of a
8012  * constrained domain, we could get by with scanning the table and checking
8013  * the constraint rather than actually rewriting it, but we don't currently
8014  * try to do that.
8015  */
8016 static bool
8017 ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno)
8018 {
8019         Assert(expr != NULL);
8020
8021         for (;;)
8022         {
8023                 /* only one varno, so no need to check that */
8024                 if (IsA(expr, Var) &&((Var *) expr)->varattno == varattno)
8025                         return false;
8026                 else if (IsA(expr, RelabelType))
8027                         expr = (Node *) ((RelabelType *) expr)->arg;
8028                 else if (IsA(expr, CoerceToDomain))
8029                 {
8030                         CoerceToDomain *d = (CoerceToDomain *) expr;
8031
8032                         if (DomainHasConstraints(d->resulttype))
8033                                 return true;
8034                         expr = (Node *) d->arg;
8035                 }
8036                 else
8037                         return true;
8038         }
8039 }
8040
8041 /*
8042  * ALTER COLUMN .. SET DATA TYPE
8043  *
8044  * Return the address of the modified column.
8045  */
8046 static ObjectAddress
8047 ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
8048                                           AlterTableCmd *cmd, LOCKMODE lockmode)
8049 {
8050         char       *colName = cmd->name;
8051         ColumnDef  *def = (ColumnDef *) cmd->def;
8052         TypeName   *typeName = def->typeName;
8053         HeapTuple       heapTup;
8054         Form_pg_attribute attTup;
8055         AttrNumber      attnum;
8056         HeapTuple       typeTuple;
8057         Form_pg_type tform;
8058         Oid                     targettype;
8059         int32           targettypmod;
8060         Oid                     targetcollid;
8061         Node       *defaultexpr;
8062         Relation        attrelation;
8063         Relation        depRel;
8064         ScanKeyData key[3];
8065         SysScanDesc scan;
8066         HeapTuple       depTup;
8067         ObjectAddress address;
8068
8069         attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
8070
8071         /* Look up the target column */
8072         heapTup = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
8073         if (!HeapTupleIsValid(heapTup))         /* shouldn't happen */
8074                 ereport(ERROR,
8075                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
8076                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
8077                                                 colName, RelationGetRelationName(rel))));
8078         attTup = (Form_pg_attribute) GETSTRUCT(heapTup);
8079         attnum = attTup->attnum;
8080
8081         /* Check for multiple ALTER TYPE on same column --- can't cope */
8082         if (attTup->atttypid != tab->oldDesc->attrs[attnum - 1]->atttypid ||
8083                 attTup->atttypmod != tab->oldDesc->attrs[attnum - 1]->atttypmod)
8084                 ereport(ERROR,
8085                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8086                                  errmsg("cannot alter type of column \"%s\" twice",
8087                                                 colName)));
8088
8089         /* Look up the target type (should not fail, since prep found it) */
8090         typeTuple = typenameType(NULL, typeName, &targettypmod);
8091         tform = (Form_pg_type) GETSTRUCT(typeTuple);
8092         targettype = HeapTupleGetOid(typeTuple);
8093         /* And the collation */
8094         targetcollid = GetColumnDefCollation(NULL, def, targettype);
8095
8096         /*
8097          * If there is a default expression for the column, get it and ensure we
8098          * can coerce it to the new datatype.  (We must do this before changing
8099          * the column type, because build_column_default itself will try to
8100          * coerce, and will not issue the error message we want if it fails.)
8101          *
8102          * We remove any implicit coercion steps at the top level of the old
8103          * default expression; this has been agreed to satisfy the principle of
8104          * least surprise.  (The conversion to the new column type should act like
8105          * it started from what the user sees as the stored expression, and the
8106          * implicit coercions aren't going to be shown.)
8107          */
8108         if (attTup->atthasdef)
8109         {
8110                 defaultexpr = build_column_default(rel, attnum);
8111                 Assert(defaultexpr);
8112                 defaultexpr = strip_implicit_coercions(defaultexpr);
8113                 defaultexpr = coerce_to_target_type(NULL,               /* no UNKNOWN params */
8114                                                                                   defaultexpr, exprType(defaultexpr),
8115                                                                                         targettype, targettypmod,
8116                                                                                         COERCION_ASSIGNMENT,
8117                                                                                         COERCE_IMPLICIT_CAST,
8118                                                                                         -1);
8119                 if (defaultexpr == NULL)
8120                         ereport(ERROR,
8121                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
8122                                          errmsg("default for column \"%s\" cannot be cast automatically to type %s",
8123                                                         colName, format_type_be(targettype))));
8124         }
8125         else
8126                 defaultexpr = NULL;
8127
8128         /*
8129          * Find everything that depends on the column (constraints, indexes, etc),
8130          * and record enough information to let us recreate the objects.
8131          *
8132          * The actual recreation does not happen here, but only after we have
8133          * performed all the individual ALTER TYPE operations.  We have to save
8134          * the info before executing ALTER TYPE, though, else the deparser will
8135          * get confused.
8136          *
8137          * There could be multiple entries for the same object, so we must check
8138          * to ensure we process each one only once.  Note: we assume that an index
8139          * that implements a constraint will not show a direct dependency on the
8140          * column.
8141          */
8142         depRel = heap_open(DependRelationId, RowExclusiveLock);
8143
8144         ScanKeyInit(&key[0],
8145                                 Anum_pg_depend_refclassid,
8146                                 BTEqualStrategyNumber, F_OIDEQ,
8147                                 ObjectIdGetDatum(RelationRelationId));
8148         ScanKeyInit(&key[1],
8149                                 Anum_pg_depend_refobjid,
8150                                 BTEqualStrategyNumber, F_OIDEQ,
8151                                 ObjectIdGetDatum(RelationGetRelid(rel)));
8152         ScanKeyInit(&key[2],
8153                                 Anum_pg_depend_refobjsubid,
8154                                 BTEqualStrategyNumber, F_INT4EQ,
8155                                 Int32GetDatum((int32) attnum));
8156
8157         scan = systable_beginscan(depRel, DependReferenceIndexId, true,
8158                                                           NULL, 3, key);
8159
8160         while (HeapTupleIsValid(depTup = systable_getnext(scan)))
8161         {
8162                 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(depTup);
8163                 ObjectAddress foundObject;
8164
8165                 /* We don't expect any PIN dependencies on columns */
8166                 if (foundDep->deptype == DEPENDENCY_PIN)
8167                         elog(ERROR, "cannot alter type of a pinned column");
8168
8169                 foundObject.classId = foundDep->classid;
8170                 foundObject.objectId = foundDep->objid;
8171                 foundObject.objectSubId = foundDep->objsubid;
8172
8173                 switch (getObjectClass(&foundObject))
8174                 {
8175                         case OCLASS_CLASS:
8176                                 {
8177                                         char            relKind = get_rel_relkind(foundObject.objectId);
8178
8179                                         if (relKind == RELKIND_INDEX)
8180                                         {
8181                                                 Assert(foundObject.objectSubId == 0);
8182                                                 if (!list_member_oid(tab->changedIndexOids, foundObject.objectId))
8183                                                 {
8184                                                         tab->changedIndexOids = lappend_oid(tab->changedIndexOids,
8185                                                                                                            foundObject.objectId);
8186                                                         tab->changedIndexDefs = lappend(tab->changedIndexDefs,
8187                                                            pg_get_indexdef_string(foundObject.objectId));
8188                                                 }
8189                                         }
8190                                         else if (relKind == RELKIND_SEQUENCE)
8191                                         {
8192                                                 /*
8193                                                  * This must be a SERIAL column's sequence.  We need
8194                                                  * not do anything to it.
8195                                                  */
8196                                                 Assert(foundObject.objectSubId == 0);
8197                                         }
8198                                         else
8199                                         {
8200                                                 /* Not expecting any other direct dependencies... */
8201                                                 elog(ERROR, "unexpected object depending on column: %s",
8202                                                          getObjectDescription(&foundObject));
8203                                         }
8204                                         break;
8205                                 }
8206
8207                         case OCLASS_CONSTRAINT:
8208                                 Assert(foundObject.objectSubId == 0);
8209                                 if (!list_member_oid(tab->changedConstraintOids,
8210                                                                          foundObject.objectId))
8211                                 {
8212                                         char       *defstring = pg_get_constraintdef_string(foundObject.objectId);
8213
8214                                         /*
8215                                          * Put NORMAL dependencies at the front of the list and
8216                                          * AUTO dependencies at the back.  This makes sure that
8217                                          * foreign-key constraints depending on this column will
8218                                          * be dropped before unique or primary-key constraints of
8219                                          * the column; which we must have because the FK
8220                                          * constraints depend on the indexes belonging to the
8221                                          * unique constraints.
8222                                          */
8223                                         if (foundDep->deptype == DEPENDENCY_NORMAL)
8224                                         {
8225                                                 tab->changedConstraintOids =
8226                                                         lcons_oid(foundObject.objectId,
8227                                                                           tab->changedConstraintOids);
8228                                                 tab->changedConstraintDefs =
8229                                                         lcons(defstring,
8230                                                                   tab->changedConstraintDefs);
8231                                         }
8232                                         else
8233                                         {
8234                                                 tab->changedConstraintOids =
8235                                                         lappend_oid(tab->changedConstraintOids,
8236                                                                                 foundObject.objectId);
8237                                                 tab->changedConstraintDefs =
8238                                                         lappend(tab->changedConstraintDefs,
8239                                                                         defstring);
8240                                         }
8241                                 }
8242                                 break;
8243
8244                         case OCLASS_REWRITE:
8245                                 /* XXX someday see if we can cope with revising views */
8246                                 ereport(ERROR,
8247                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8248                                                  errmsg("cannot alter type of a column used by a view or rule"),
8249                                                  errdetail("%s depends on column \"%s\"",
8250                                                                    getObjectDescription(&foundObject),
8251                                                                    colName)));
8252                                 break;
8253
8254                         case OCLASS_TRIGGER:
8255
8256                                 /*
8257                                  * A trigger can depend on a column because the column is
8258                                  * specified as an update target, or because the column is
8259                                  * used in the trigger's WHEN condition.  The first case would
8260                                  * not require any extra work, but the second case would
8261                                  * require updating the WHEN expression, which will take a
8262                                  * significant amount of new code.  Since we can't easily tell
8263                                  * which case applies, we punt for both.  FIXME someday.
8264                                  */
8265                                 ereport(ERROR,
8266                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8267                                                  errmsg("cannot alter type of a column used in a trigger definition"),
8268                                                  errdetail("%s depends on column \"%s\"",
8269                                                                    getObjectDescription(&foundObject),
8270                                                                    colName)));
8271                                 break;
8272
8273                         case OCLASS_POLICY:
8274
8275                                 /*
8276                                  * A policy can depend on a column because the column is
8277                                  * specified in the policy's USING or WITH CHECK qual
8278                                  * expressions.  It might be possible to rewrite and recheck
8279                                  * the policy expression, but punt for now.  It's certainly
8280                                  * easy enough to remove and recreate the policy; still, FIXME
8281                                  * someday.
8282                                  */
8283                                 ereport(ERROR,
8284                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8285                                                  errmsg("cannot alter type of a column used in a policy definition"),
8286                                                  errdetail("%s depends on column \"%s\"",
8287                                                                    getObjectDescription(&foundObject),
8288                                                                    colName)));
8289                                 break;
8290
8291                         case OCLASS_DEFAULT:
8292
8293                                 /*
8294                                  * Ignore the column's default expression, since we will fix
8295                                  * it below.
8296                                  */
8297                                 Assert(defaultexpr);
8298                                 break;
8299
8300                         case OCLASS_PROC:
8301                         case OCLASS_TYPE:
8302                         case OCLASS_CAST:
8303                         case OCLASS_COLLATION:
8304                         case OCLASS_CONVERSION:
8305                         case OCLASS_LANGUAGE:
8306                         case OCLASS_LARGEOBJECT:
8307                         case OCLASS_OPERATOR:
8308                         case OCLASS_OPCLASS:
8309                         case OCLASS_OPFAMILY:
8310                         case OCLASS_AMOP:
8311                         case OCLASS_AMPROC:
8312                         case OCLASS_SCHEMA:
8313                         case OCLASS_TSPARSER:
8314                         case OCLASS_TSDICT:
8315                         case OCLASS_TSTEMPLATE:
8316                         case OCLASS_TSCONFIG:
8317                         case OCLASS_ROLE:
8318                         case OCLASS_DATABASE:
8319                         case OCLASS_TBLSPACE:
8320                         case OCLASS_FDW:
8321                         case OCLASS_FOREIGN_SERVER:
8322                         case OCLASS_USER_MAPPING:
8323                         case OCLASS_DEFACL:
8324                         case OCLASS_EXTENSION:
8325
8326                                 /*
8327                                  * We don't expect any of these sorts of objects to depend on
8328                                  * a column.
8329                                  */
8330                                 elog(ERROR, "unexpected object depending on column: %s",
8331                                          getObjectDescription(&foundObject));
8332                                 break;
8333
8334                         default:
8335                                 elog(ERROR, "unrecognized object class: %u",
8336                                          foundObject.classId);
8337                 }
8338         }
8339
8340         systable_endscan(scan);
8341
8342         /*
8343          * Now scan for dependencies of this column on other things.  The only
8344          * thing we should find is the dependency on the column datatype, which we
8345          * want to remove, and possibly a collation dependency.
8346          */
8347         ScanKeyInit(&key[0],
8348                                 Anum_pg_depend_classid,
8349                                 BTEqualStrategyNumber, F_OIDEQ,
8350                                 ObjectIdGetDatum(RelationRelationId));
8351         ScanKeyInit(&key[1],
8352                                 Anum_pg_depend_objid,
8353                                 BTEqualStrategyNumber, F_OIDEQ,
8354                                 ObjectIdGetDatum(RelationGetRelid(rel)));
8355         ScanKeyInit(&key[2],
8356                                 Anum_pg_depend_objsubid,
8357                                 BTEqualStrategyNumber, F_INT4EQ,
8358                                 Int32GetDatum((int32) attnum));
8359
8360         scan = systable_beginscan(depRel, DependDependerIndexId, true,
8361                                                           NULL, 3, key);
8362
8363         while (HeapTupleIsValid(depTup = systable_getnext(scan)))
8364         {
8365                 Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(depTup);
8366
8367                 if (foundDep->deptype != DEPENDENCY_NORMAL)
8368                         elog(ERROR, "found unexpected dependency type '%c'",
8369                                  foundDep->deptype);
8370                 if (!(foundDep->refclassid == TypeRelationId &&
8371                           foundDep->refobjid == attTup->atttypid) &&
8372                         !(foundDep->refclassid == CollationRelationId &&
8373                           foundDep->refobjid == attTup->attcollation))
8374                         elog(ERROR, "found unexpected dependency for column");
8375
8376                 simple_heap_delete(depRel, &depTup->t_self);
8377         }
8378
8379         systable_endscan(scan);
8380
8381         heap_close(depRel, RowExclusiveLock);
8382
8383         /*
8384          * Here we go --- change the recorded column type and collation.  (Note
8385          * heapTup is a copy of the syscache entry, so okay to scribble on.)
8386          */
8387         attTup->atttypid = targettype;
8388         attTup->atttypmod = targettypmod;
8389         attTup->attcollation = targetcollid;
8390         attTup->attndims = list_length(typeName->arrayBounds);
8391         attTup->attlen = tform->typlen;
8392         attTup->attbyval = tform->typbyval;
8393         attTup->attalign = tform->typalign;
8394         attTup->attstorage = tform->typstorage;
8395
8396         ReleaseSysCache(typeTuple);
8397
8398         simple_heap_update(attrelation, &heapTup->t_self, heapTup);
8399
8400         /* keep system catalog indexes current */
8401         CatalogUpdateIndexes(attrelation, heapTup);
8402
8403         heap_close(attrelation, RowExclusiveLock);
8404
8405         /* Install dependencies on new datatype and collation */
8406         add_column_datatype_dependency(RelationGetRelid(rel), attnum, targettype);
8407         add_column_collation_dependency(RelationGetRelid(rel), attnum, targetcollid);
8408
8409         /*
8410          * Drop any pg_statistic entry for the column, since it's now wrong type
8411          */
8412         RemoveStatistics(RelationGetRelid(rel), attnum);
8413
8414         InvokeObjectPostAlterHook(RelationRelationId,
8415                                                           RelationGetRelid(rel), attnum);
8416
8417         /*
8418          * Update the default, if present, by brute force --- remove and re-add
8419          * the default.  Probably unsafe to take shortcuts, since the new version
8420          * may well have additional dependencies.  (It's okay to do this now,
8421          * rather than after other ALTER TYPE commands, since the default won't
8422          * depend on other column types.)
8423          */
8424         if (defaultexpr)
8425         {
8426                 /* Must make new row visible since it will be updated again */
8427                 CommandCounterIncrement();
8428
8429                 /*
8430                  * We use RESTRICT here for safety, but at present we do not expect
8431                  * anything to depend on the default.
8432                  */
8433                 RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true,
8434                                                   true);
8435
8436                 StoreAttrDefault(rel, attnum, defaultexpr, true);
8437         }
8438
8439         ObjectAddressSubSet(address, RelationRelationId,
8440                                                 RelationGetRelid(rel), attnum);
8441
8442         /* Cleanup */
8443         heap_freetuple(heapTup);
8444
8445         return address;
8446 }
8447
8448 /*
8449  * Returns the address of the modified column
8450  */
8451 static ObjectAddress
8452 ATExecAlterColumnGenericOptions(Relation rel,
8453                                                                 const char *colName,
8454                                                                 List *options,
8455                                                                 LOCKMODE lockmode)
8456 {
8457         Relation        ftrel;
8458         Relation        attrel;
8459         ForeignServer *server;
8460         ForeignDataWrapper *fdw;
8461         HeapTuple       tuple;
8462         HeapTuple       newtuple;
8463         bool            isnull;
8464         Datum           repl_val[Natts_pg_attribute];
8465         bool            repl_null[Natts_pg_attribute];
8466         bool            repl_repl[Natts_pg_attribute];
8467         Datum           datum;
8468         Form_pg_foreign_table fttableform;
8469         Form_pg_attribute atttableform;
8470         AttrNumber      attnum;
8471         ObjectAddress address;
8472
8473         if (options == NIL)
8474                 return InvalidObjectAddress;
8475
8476         /* First, determine FDW validator associated to the foreign table. */
8477         ftrel = heap_open(ForeignTableRelationId, AccessShareLock);
8478         tuple = SearchSysCache1(FOREIGNTABLEREL, rel->rd_id);
8479         if (!HeapTupleIsValid(tuple))
8480                 ereport(ERROR,
8481                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
8482                                  errmsg("foreign table \"%s\" does not exist",
8483                                                 RelationGetRelationName(rel))));
8484         fttableform = (Form_pg_foreign_table) GETSTRUCT(tuple);
8485         server = GetForeignServer(fttableform->ftserver);
8486         fdw = GetForeignDataWrapper(server->fdwid);
8487
8488         heap_close(ftrel, AccessShareLock);
8489         ReleaseSysCache(tuple);
8490
8491         attrel = heap_open(AttributeRelationId, RowExclusiveLock);
8492         tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
8493         if (!HeapTupleIsValid(tuple))
8494                 ereport(ERROR,
8495                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
8496                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
8497                                                 colName, RelationGetRelationName(rel))));
8498
8499         /* Prevent them from altering a system attribute */
8500         atttableform = (Form_pg_attribute) GETSTRUCT(tuple);
8501         attnum = atttableform->attnum;
8502         if (attnum <= 0)
8503                 ereport(ERROR,
8504                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8505                                  errmsg("cannot alter system column \"%s\"", colName)));
8506
8507
8508         /* Initialize buffers for new tuple values */
8509         memset(repl_val, 0, sizeof(repl_val));
8510         memset(repl_null, false, sizeof(repl_null));
8511         memset(repl_repl, false, sizeof(repl_repl));
8512
8513         /* Extract the current options */
8514         datum = SysCacheGetAttr(ATTNAME,
8515                                                         tuple,
8516                                                         Anum_pg_attribute_attfdwoptions,
8517                                                         &isnull);
8518         if (isnull)
8519                 datum = PointerGetDatum(NULL);
8520
8521         /* Transform the options */
8522         datum = transformGenericOptions(AttributeRelationId,
8523                                                                         datum,
8524                                                                         options,
8525                                                                         fdw->fdwvalidator);
8526
8527         if (PointerIsValid(DatumGetPointer(datum)))
8528                 repl_val[Anum_pg_attribute_attfdwoptions - 1] = datum;
8529         else
8530                 repl_null[Anum_pg_attribute_attfdwoptions - 1] = true;
8531
8532         repl_repl[Anum_pg_attribute_attfdwoptions - 1] = true;
8533
8534         /* Everything looks good - update the tuple */
8535
8536         newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrel),
8537                                                                  repl_val, repl_null, repl_repl);
8538
8539         simple_heap_update(attrel, &newtuple->t_self, newtuple);
8540         CatalogUpdateIndexes(attrel, newtuple);
8541
8542         InvokeObjectPostAlterHook(RelationRelationId,
8543                                                           RelationGetRelid(rel),
8544                                                           atttableform->attnum);
8545         ObjectAddressSubSet(address, RelationRelationId,
8546                                                 RelationGetRelid(rel), attnum);
8547
8548         ReleaseSysCache(tuple);
8549
8550         heap_close(attrel, RowExclusiveLock);
8551
8552         heap_freetuple(newtuple);
8553
8554         return address;
8555 }
8556
8557 /*
8558  * Cleanup after we've finished all the ALTER TYPE operations for a
8559  * particular relation.  We have to drop and recreate all the indexes
8560  * and constraints that depend on the altered columns.
8561  */
8562 static void
8563 ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
8564 {
8565         ObjectAddress obj;
8566         ListCell   *def_item;
8567         ListCell   *oid_item;
8568
8569         /*
8570          * Re-parse the index and constraint definitions, and attach them to the
8571          * appropriate work queue entries.  We do this before dropping because in
8572          * the case of a FOREIGN KEY constraint, we might not yet have exclusive
8573          * lock on the table the constraint is attached to, and we need to get
8574          * that before dropping.  It's safe because the parser won't actually look
8575          * at the catalogs to detect the existing entry.
8576          *
8577          * We can't rely on the output of deparsing to tell us which relation to
8578          * operate on, because concurrent activity might have made the name
8579          * resolve differently.  Instead, we've got to use the OID of the
8580          * constraint or index we're processing to figure out which relation to
8581          * operate on.
8582          */
8583         forboth(oid_item, tab->changedConstraintOids,
8584                         def_item, tab->changedConstraintDefs)
8585         {
8586                 Oid                     oldId = lfirst_oid(oid_item);
8587                 Oid                     relid;
8588                 Oid                     confrelid;
8589
8590                 get_constraint_relation_oids(oldId, &relid, &confrelid);
8591                 ATPostAlterTypeParse(oldId, relid, confrelid,
8592                                                          (char *) lfirst(def_item),
8593                                                          wqueue, lockmode, tab->rewrite);
8594         }
8595         forboth(oid_item, tab->changedIndexOids,
8596                         def_item, tab->changedIndexDefs)
8597         {
8598                 Oid                     oldId = lfirst_oid(oid_item);
8599                 Oid                     relid;
8600
8601                 relid = IndexGetRelation(oldId, false);
8602                 ATPostAlterTypeParse(oldId, relid, InvalidOid,
8603                                                          (char *) lfirst(def_item),
8604                                                          wqueue, lockmode, tab->rewrite);
8605         }
8606
8607         /*
8608          * Now we can drop the existing constraints and indexes --- constraints
8609          * first, since some of them might depend on the indexes.  In fact, we
8610          * have to delete FOREIGN KEY constraints before UNIQUE constraints, but
8611          * we already ordered the constraint list to ensure that would happen. It
8612          * should be okay to use DROP_RESTRICT here, since nothing else should be
8613          * depending on these objects.
8614          */
8615         foreach(oid_item, tab->changedConstraintOids)
8616         {
8617                 obj.classId = ConstraintRelationId;
8618                 obj.objectId = lfirst_oid(oid_item);
8619                 obj.objectSubId = 0;
8620                 performDeletion(&obj, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
8621         }
8622
8623         foreach(oid_item, tab->changedIndexOids)
8624         {
8625                 obj.classId = RelationRelationId;
8626                 obj.objectId = lfirst_oid(oid_item);
8627                 obj.objectSubId = 0;
8628                 performDeletion(&obj, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
8629         }
8630
8631         /*
8632          * The objects will get recreated during subsequent passes over the work
8633          * queue.
8634          */
8635 }
8636
8637 static void
8638 ATPostAlterTypeParse(Oid oldId, Oid oldRelId, Oid refRelId, char *cmd,
8639                                          List **wqueue, LOCKMODE lockmode, bool rewrite)
8640 {
8641         List       *raw_parsetree_list;
8642         List       *querytree_list;
8643         ListCell   *list_item;
8644         Relation        rel;
8645
8646         /*
8647          * We expect that we will get only ALTER TABLE and CREATE INDEX
8648          * statements. Hence, there is no need to pass them through
8649          * parse_analyze() or the rewriter, but instead we need to pass them
8650          * through parse_utilcmd.c to make them ready for execution.
8651          */
8652         raw_parsetree_list = raw_parser(cmd);
8653         querytree_list = NIL;
8654         foreach(list_item, raw_parsetree_list)
8655         {
8656                 Node       *stmt = (Node *) lfirst(list_item);
8657
8658                 if (IsA(stmt, IndexStmt))
8659                         querytree_list = lappend(querytree_list,
8660                                                                          transformIndexStmt(oldRelId,
8661                                                                                                                 (IndexStmt *) stmt,
8662                                                                                                                 cmd));
8663                 else if (IsA(stmt, AlterTableStmt))
8664                         querytree_list = list_concat(querytree_list,
8665                                                                                  transformAlterTableStmt(oldRelId,
8666                                                                                                          (AlterTableStmt *) stmt,
8667                                                                                                                                  cmd));
8668                 else
8669                         querytree_list = lappend(querytree_list, stmt);
8670         }
8671
8672         /* Caller should already have acquired whatever lock we need. */
8673         rel = relation_open(oldRelId, NoLock);
8674
8675         /*
8676          * Attach each generated command to the proper place in the work queue.
8677          * Note this could result in creation of entirely new work-queue entries.
8678          *
8679          * Also note that we have to tweak the command subtypes, because it turns
8680          * out that re-creation of indexes and constraints has to act a bit
8681          * differently from initial creation.
8682          */
8683         foreach(list_item, querytree_list)
8684         {
8685                 Node       *stm = (Node *) lfirst(list_item);
8686                 AlteredTableInfo *tab;
8687
8688                 tab = ATGetQueueEntry(wqueue, rel);
8689
8690                 if (IsA(stm, IndexStmt))
8691                 {
8692                         IndexStmt  *stmt = (IndexStmt *) stm;
8693                         AlterTableCmd *newcmd;
8694
8695                         if (!rewrite)
8696                                 TryReuseIndex(oldId, stmt);
8697                         /* keep the index's comment */
8698                         stmt->idxcomment = GetComment(oldId, RelationRelationId, 0);
8699
8700                         newcmd = makeNode(AlterTableCmd);
8701                         newcmd->subtype = AT_ReAddIndex;
8702                         newcmd->def = (Node *) stmt;
8703                         tab->subcmds[AT_PASS_OLD_INDEX] =
8704                                 lappend(tab->subcmds[AT_PASS_OLD_INDEX], newcmd);
8705                 }
8706                 else if (IsA(stm, AlterTableStmt))
8707                 {
8708                         AlterTableStmt *stmt = (AlterTableStmt *) stm;
8709                         ListCell   *lcmd;
8710
8711                         foreach(lcmd, stmt->cmds)
8712                         {
8713                                 AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
8714
8715                                 if (cmd->subtype == AT_AddIndex)
8716                                 {
8717                                         IndexStmt  *indstmt;
8718                                         Oid                     indoid;
8719
8720                                         Assert(IsA(cmd->def, IndexStmt));
8721
8722                                         indstmt = (IndexStmt *) cmd->def;
8723                                         indoid = get_constraint_index(oldId);
8724
8725                                         if (!rewrite)
8726                                                 TryReuseIndex(indoid, indstmt);
8727                                         /* keep any comment on the index */
8728                                         indstmt->idxcomment = GetComment(indoid,
8729                                                                                                          RelationRelationId, 0);
8730
8731                                         cmd->subtype = AT_ReAddIndex;
8732                                         tab->subcmds[AT_PASS_OLD_INDEX] =
8733                                                 lappend(tab->subcmds[AT_PASS_OLD_INDEX], cmd);
8734
8735                                         /* recreate any comment on the constraint */
8736                                         RebuildConstraintComment(tab,
8737                                                                                          AT_PASS_OLD_INDEX,
8738                                                                                          oldId,
8739                                                                                          rel, indstmt->idxname);
8740                                 }
8741                                 else if (cmd->subtype == AT_AddConstraint)
8742                                 {
8743                                         Constraint *con;
8744
8745                                         Assert(IsA(cmd->def, Constraint));
8746
8747                                         con = (Constraint *) cmd->def;
8748                                         con->old_pktable_oid = refRelId;
8749                                         /* rewriting neither side of a FK */
8750                                         if (con->contype == CONSTR_FOREIGN &&
8751                                                 !rewrite && tab->rewrite == 0)
8752                                                 TryReuseForeignKey(oldId, con);
8753                                         cmd->subtype = AT_ReAddConstraint;
8754                                         tab->subcmds[AT_PASS_OLD_CONSTR] =
8755                                                 lappend(tab->subcmds[AT_PASS_OLD_CONSTR], cmd);
8756
8757                                         /* recreate any comment on the constraint */
8758                                         RebuildConstraintComment(tab,
8759                                                                                          AT_PASS_OLD_CONSTR,
8760                                                                                          oldId,
8761                                                                                          rel, con->conname);
8762                                 }
8763                                 else
8764                                         elog(ERROR, "unexpected statement type: %d",
8765                                                  (int) cmd->subtype);
8766                         }
8767                 }
8768                 else
8769                         elog(ERROR, "unexpected statement type: %d",
8770                                  (int) nodeTag(stm));
8771         }
8772
8773         relation_close(rel, NoLock);
8774 }
8775
8776 /*
8777  * Subroutine for ATPostAlterTypeParse() to recreate a comment entry for
8778  * a constraint that is being re-added.
8779  */
8780 static void
8781 RebuildConstraintComment(AlteredTableInfo *tab, int pass, Oid objid,
8782                                                  Relation rel, char *conname)
8783 {
8784         CommentStmt *cmd;
8785         char       *comment_str;
8786         AlterTableCmd *newcmd;
8787
8788         /* Look for comment for object wanted, and leave if none */
8789         comment_str = GetComment(objid, ConstraintRelationId, 0);
8790         if (comment_str == NULL)
8791                 return;
8792
8793         /* Build node CommentStmt */
8794         cmd = makeNode(CommentStmt);
8795         cmd->objtype = OBJECT_TABCONSTRAINT;
8796         cmd->objname = list_make3(
8797                                    makeString(get_namespace_name(RelationGetNamespace(rel))),
8798                                                           makeString(RelationGetRelationName(rel)),
8799                                                           makeString(conname));
8800         cmd->objargs = NIL;
8801         cmd->comment = comment_str;
8802
8803         /* Append it to list of commands */
8804         newcmd = makeNode(AlterTableCmd);
8805         newcmd->subtype = AT_ReAddComment;
8806         newcmd->def = (Node *) cmd;
8807         tab->subcmds[pass] = lappend(tab->subcmds[pass], newcmd);
8808 }
8809
8810 /*
8811  * Subroutine for ATPostAlterTypeParse().  Calls out to CheckIndexCompatible()
8812  * for the real analysis, then mutates the IndexStmt based on that verdict.
8813  */
8814 static void
8815 TryReuseIndex(Oid oldId, IndexStmt *stmt)
8816 {
8817         if (CheckIndexCompatible(oldId,
8818                                                          stmt->accessMethod,
8819                                                          stmt->indexParams,
8820                                                          stmt->excludeOpNames))
8821         {
8822                 Relation        irel = index_open(oldId, NoLock);
8823
8824                 stmt->oldNode = irel->rd_node.relNode;
8825                 index_close(irel, NoLock);
8826         }
8827 }
8828
8829 /*
8830  * Subroutine for ATPostAlterTypeParse().
8831  *
8832  * Stash the old P-F equality operator into the Constraint node, for possible
8833  * use by ATAddForeignKeyConstraint() in determining whether revalidation of
8834  * this constraint can be skipped.
8835  */
8836 static void
8837 TryReuseForeignKey(Oid oldId, Constraint *con)
8838 {
8839         HeapTuple       tup;
8840         Datum           adatum;
8841         bool            isNull;
8842         ArrayType  *arr;
8843         Oid                *rawarr;
8844         int                     numkeys;
8845         int                     i;
8846
8847         Assert(con->contype == CONSTR_FOREIGN);
8848         Assert(con->old_conpfeqop == NIL);      /* already prepared this node */
8849
8850         tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(oldId));
8851         if (!HeapTupleIsValid(tup)) /* should not happen */
8852                 elog(ERROR, "cache lookup failed for constraint %u", oldId);
8853
8854         adatum = SysCacheGetAttr(CONSTROID, tup,
8855                                                          Anum_pg_constraint_conpfeqop, &isNull);
8856         if (isNull)
8857                 elog(ERROR, "null conpfeqop for constraint %u", oldId);
8858         arr = DatumGetArrayTypeP(adatum);       /* ensure not toasted */
8859         numkeys = ARR_DIMS(arr)[0];
8860         /* test follows the one in ri_FetchConstraintInfo() */
8861         if (ARR_NDIM(arr) != 1 ||
8862                 ARR_HASNULL(arr) ||
8863                 ARR_ELEMTYPE(arr) != OIDOID)
8864                 elog(ERROR, "conpfeqop is not a 1-D Oid array");
8865         rawarr = (Oid *) ARR_DATA_PTR(arr);
8866
8867         /* stash a List of the operator Oids in our Constraint node */
8868         for (i = 0; i < numkeys; i++)
8869                 con->old_conpfeqop = lcons_oid(rawarr[i], con->old_conpfeqop);
8870
8871         ReleaseSysCache(tup);
8872 }
8873
8874 /*
8875  * ALTER TABLE OWNER
8876  *
8877  * recursing is true if we are recursing from a table to its indexes,
8878  * sequences, or toast table.  We don't allow the ownership of those things to
8879  * be changed separately from the parent table.  Also, we can skip permission
8880  * checks (this is necessary not just an optimization, else we'd fail to
8881  * handle toast tables properly).
8882  *
8883  * recursing is also true if ALTER TYPE OWNER is calling us to fix up a
8884  * free-standing composite type.
8885  */
8886 void
8887 ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
8888 {
8889         Relation        target_rel;
8890         Relation        class_rel;
8891         HeapTuple       tuple;
8892         Form_pg_class tuple_class;
8893
8894         /*
8895          * Get exclusive lock till end of transaction on the target table. Use
8896          * relation_open so that we can work on indexes and sequences.
8897          */
8898         target_rel = relation_open(relationOid, lockmode);
8899
8900         /* Get its pg_class tuple, too */
8901         class_rel = heap_open(RelationRelationId, RowExclusiveLock);
8902
8903         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationOid));
8904         if (!HeapTupleIsValid(tuple))
8905                 elog(ERROR, "cache lookup failed for relation %u", relationOid);
8906         tuple_class = (Form_pg_class) GETSTRUCT(tuple);
8907
8908         /* Can we change the ownership of this tuple? */
8909         switch (tuple_class->relkind)
8910         {
8911                 case RELKIND_RELATION:
8912                 case RELKIND_VIEW:
8913                 case RELKIND_MATVIEW:
8914                 case RELKIND_FOREIGN_TABLE:
8915                         /* ok to change owner */
8916                         break;
8917                 case RELKIND_INDEX:
8918                         if (!recursing)
8919                         {
8920                                 /*
8921                                  * Because ALTER INDEX OWNER used to be allowed, and in fact
8922                                  * is generated by old versions of pg_dump, we give a warning
8923                                  * and do nothing rather than erroring out.  Also, to avoid
8924                                  * unnecessary chatter while restoring those old dumps, say
8925                                  * nothing at all if the command would be a no-op anyway.
8926                                  */
8927                                 if (tuple_class->relowner != newOwnerId)
8928                                         ereport(WARNING,
8929                                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8930                                                          errmsg("cannot change owner of index \"%s\"",
8931                                                                         NameStr(tuple_class->relname)),
8932                                                          errhint("Change the ownership of the index's table, instead.")));
8933                                 /* quick hack to exit via the no-op path */
8934                                 newOwnerId = tuple_class->relowner;
8935                         }
8936                         break;
8937                 case RELKIND_SEQUENCE:
8938                         if (!recursing &&
8939                                 tuple_class->relowner != newOwnerId)
8940                         {
8941                                 /* if it's an owned sequence, disallow changing it by itself */
8942                                 Oid                     tableId;
8943                                 int32           colId;
8944
8945                                 if (sequenceIsOwned(relationOid, &tableId, &colId))
8946                                         ereport(ERROR,
8947                                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
8948                                                          errmsg("cannot change owner of sequence \"%s\"",
8949                                                                         NameStr(tuple_class->relname)),
8950                                           errdetail("Sequence \"%s\" is linked to table \"%s\".",
8951                                                                 NameStr(tuple_class->relname),
8952                                                                 get_rel_name(tableId))));
8953                         }
8954                         break;
8955                 case RELKIND_COMPOSITE_TYPE:
8956                         if (recursing)
8957                                 break;
8958                         ereport(ERROR,
8959                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8960                                          errmsg("\"%s\" is a composite type",
8961                                                         NameStr(tuple_class->relname)),
8962                                          errhint("Use ALTER TYPE instead.")));
8963                         break;
8964                 case RELKIND_TOASTVALUE:
8965                         if (recursing)
8966                                 break;
8967                         /* FALL THRU */
8968                 default:
8969                         ereport(ERROR,
8970                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
8971                         errmsg("\"%s\" is not a table, view, sequence, or foreign table",
8972                                    NameStr(tuple_class->relname))));
8973         }
8974
8975         /*
8976          * If the new owner is the same as the existing owner, consider the
8977          * command to have succeeded.  This is for dump restoration purposes.
8978          */
8979         if (tuple_class->relowner != newOwnerId)
8980         {
8981                 Datum           repl_val[Natts_pg_class];
8982                 bool            repl_null[Natts_pg_class];
8983                 bool            repl_repl[Natts_pg_class];
8984                 Acl                *newAcl;
8985                 Datum           aclDatum;
8986                 bool            isNull;
8987                 HeapTuple       newtuple;
8988
8989                 /* skip permission checks when recursing to index or toast table */
8990                 if (!recursing)
8991                 {
8992                         /* Superusers can always do it */
8993                         if (!superuser())
8994                         {
8995                                 Oid                     namespaceOid = tuple_class->relnamespace;
8996                                 AclResult       aclresult;
8997
8998                                 /* Otherwise, must be owner of the existing object */
8999                                 if (!pg_class_ownercheck(relationOid, GetUserId()))
9000                                         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
9001                                                                    RelationGetRelationName(target_rel));
9002
9003                                 /* Must be able to become new owner */
9004                                 check_is_member_of_role(GetUserId(), newOwnerId);
9005
9006                                 /* New owner must have CREATE privilege on namespace */
9007                                 aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
9008                                                                                                   ACL_CREATE);
9009                                 if (aclresult != ACLCHECK_OK)
9010                                         aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
9011                                                                    get_namespace_name(namespaceOid));
9012                         }
9013                 }
9014
9015                 memset(repl_null, false, sizeof(repl_null));
9016                 memset(repl_repl, false, sizeof(repl_repl));
9017
9018                 repl_repl[Anum_pg_class_relowner - 1] = true;
9019                 repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId);
9020
9021                 /*
9022                  * Determine the modified ACL for the new owner.  This is only
9023                  * necessary when the ACL is non-null.
9024                  */
9025                 aclDatum = SysCacheGetAttr(RELOID, tuple,
9026                                                                    Anum_pg_class_relacl,
9027                                                                    &isNull);
9028                 if (!isNull)
9029                 {
9030                         newAcl = aclnewowner(DatumGetAclP(aclDatum),
9031                                                                  tuple_class->relowner, newOwnerId);
9032                         repl_repl[Anum_pg_class_relacl - 1] = true;
9033                         repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl);
9034                 }
9035
9036                 newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl);
9037
9038                 simple_heap_update(class_rel, &newtuple->t_self, newtuple);
9039                 CatalogUpdateIndexes(class_rel, newtuple);
9040
9041                 heap_freetuple(newtuple);
9042
9043                 /*
9044                  * We must similarly update any per-column ACLs to reflect the new
9045                  * owner; for neatness reasons that's split out as a subroutine.
9046                  */
9047                 change_owner_fix_column_acls(relationOid,
9048                                                                          tuple_class->relowner,
9049                                                                          newOwnerId);
9050
9051                 /*
9052                  * Update owner dependency reference, if any.  A composite type has
9053                  * none, because it's tracked for the pg_type entry instead of here;
9054                  * indexes and TOAST tables don't have their own entries either.
9055                  */
9056                 if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE &&
9057                         tuple_class->relkind != RELKIND_INDEX &&
9058                         tuple_class->relkind != RELKIND_TOASTVALUE)
9059                         changeDependencyOnOwner(RelationRelationId, relationOid,
9060                                                                         newOwnerId);
9061
9062                 /*
9063                  * Also change the ownership of the table's row type, if it has one
9064                  */
9065                 if (tuple_class->relkind != RELKIND_INDEX)
9066                         AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId,
9067                                                          tuple_class->relkind == RELKIND_COMPOSITE_TYPE);
9068
9069                 /*
9070                  * If we are operating on a table or materialized view, also change
9071                  * the ownership of any indexes and sequences that belong to the
9072                  * relation, as well as its toast table (if it has one).
9073                  */
9074                 if (tuple_class->relkind == RELKIND_RELATION ||
9075                         tuple_class->relkind == RELKIND_MATVIEW ||
9076                         tuple_class->relkind == RELKIND_TOASTVALUE)
9077                 {
9078                         List       *index_oid_list;
9079                         ListCell   *i;
9080
9081                         /* Find all the indexes belonging to this relation */
9082                         index_oid_list = RelationGetIndexList(target_rel);
9083
9084                         /* For each index, recursively change its ownership */
9085                         foreach(i, index_oid_list)
9086                                 ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
9087
9088                         list_free(index_oid_list);
9089                 }
9090
9091                 if (tuple_class->relkind == RELKIND_RELATION ||
9092                         tuple_class->relkind == RELKIND_MATVIEW)
9093                 {
9094                         /* If it has a toast table, recurse to change its ownership */
9095                         if (tuple_class->reltoastrelid != InvalidOid)
9096                                 ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerId,
9097                                                                   true, lockmode);
9098
9099                         /* If it has dependent sequences, recurse to change them too */
9100                         change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
9101                 }
9102         }
9103
9104         InvokeObjectPostAlterHook(RelationRelationId, relationOid, 0);
9105
9106         ReleaseSysCache(tuple);
9107         heap_close(class_rel, RowExclusiveLock);
9108         relation_close(target_rel, NoLock);
9109 }
9110
9111 /*
9112  * change_owner_fix_column_acls
9113  *
9114  * Helper function for ATExecChangeOwner.  Scan the columns of the table
9115  * and fix any non-null column ACLs to reflect the new owner.
9116  */
9117 static void
9118 change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId)
9119 {
9120         Relation        attRelation;
9121         SysScanDesc scan;
9122         ScanKeyData key[1];
9123         HeapTuple       attributeTuple;
9124
9125         attRelation = heap_open(AttributeRelationId, RowExclusiveLock);
9126         ScanKeyInit(&key[0],
9127                                 Anum_pg_attribute_attrelid,
9128                                 BTEqualStrategyNumber, F_OIDEQ,
9129                                 ObjectIdGetDatum(relationOid));
9130         scan = systable_beginscan(attRelation, AttributeRelidNumIndexId,
9131                                                           true, NULL, 1, key);
9132         while (HeapTupleIsValid(attributeTuple = systable_getnext(scan)))
9133         {
9134                 Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple);
9135                 Datum           repl_val[Natts_pg_attribute];
9136                 bool            repl_null[Natts_pg_attribute];
9137                 bool            repl_repl[Natts_pg_attribute];
9138                 Acl                *newAcl;
9139                 Datum           aclDatum;
9140                 bool            isNull;
9141                 HeapTuple       newtuple;
9142
9143                 /* Ignore dropped columns */
9144                 if (att->attisdropped)
9145                         continue;
9146
9147                 aclDatum = heap_getattr(attributeTuple,
9148                                                                 Anum_pg_attribute_attacl,
9149                                                                 RelationGetDescr(attRelation),
9150                                                                 &isNull);
9151                 /* Null ACLs do not require changes */
9152                 if (isNull)
9153                         continue;
9154
9155                 memset(repl_null, false, sizeof(repl_null));
9156                 memset(repl_repl, false, sizeof(repl_repl));
9157
9158                 newAcl = aclnewowner(DatumGetAclP(aclDatum),
9159                                                          oldOwnerId, newOwnerId);
9160                 repl_repl[Anum_pg_attribute_attacl - 1] = true;
9161                 repl_val[Anum_pg_attribute_attacl - 1] = PointerGetDatum(newAcl);
9162
9163                 newtuple = heap_modify_tuple(attributeTuple,
9164                                                                          RelationGetDescr(attRelation),
9165                                                                          repl_val, repl_null, repl_repl);
9166
9167                 simple_heap_update(attRelation, &newtuple->t_self, newtuple);
9168                 CatalogUpdateIndexes(attRelation, newtuple);
9169
9170                 heap_freetuple(newtuple);
9171         }
9172         systable_endscan(scan);
9173         heap_close(attRelation, RowExclusiveLock);
9174 }
9175
9176 /*
9177  * change_owner_recurse_to_sequences
9178  *
9179  * Helper function for ATExecChangeOwner.  Examines pg_depend searching
9180  * for sequences that are dependent on serial columns, and changes their
9181  * ownership.
9182  */
9183 static void
9184 change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lockmode)
9185 {
9186         Relation        depRel;
9187         SysScanDesc scan;
9188         ScanKeyData key[2];
9189         HeapTuple       tup;
9190
9191         /*
9192          * SERIAL sequences are those having an auto dependency on one of the
9193          * table's columns (we don't care *which* column, exactly).
9194          */
9195         depRel = heap_open(DependRelationId, AccessShareLock);
9196
9197         ScanKeyInit(&key[0],
9198                                 Anum_pg_depend_refclassid,
9199                                 BTEqualStrategyNumber, F_OIDEQ,
9200                                 ObjectIdGetDatum(RelationRelationId));
9201         ScanKeyInit(&key[1],
9202                                 Anum_pg_depend_refobjid,
9203                                 BTEqualStrategyNumber, F_OIDEQ,
9204                                 ObjectIdGetDatum(relationOid));
9205         /* we leave refobjsubid unspecified */
9206
9207         scan = systable_beginscan(depRel, DependReferenceIndexId, true,
9208                                                           NULL, 2, key);
9209
9210         while (HeapTupleIsValid(tup = systable_getnext(scan)))
9211         {
9212                 Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
9213                 Relation        seqRel;
9214
9215                 /* skip dependencies other than auto dependencies on columns */
9216                 if (depForm->refobjsubid == 0 ||
9217                         depForm->classid != RelationRelationId ||
9218                         depForm->objsubid != 0 ||
9219                         depForm->deptype != DEPENDENCY_AUTO)
9220                         continue;
9221
9222                 /* Use relation_open just in case it's an index */
9223                 seqRel = relation_open(depForm->objid, lockmode);
9224
9225                 /* skip non-sequence relations */
9226                 if (RelationGetForm(seqRel)->relkind != RELKIND_SEQUENCE)
9227                 {
9228                         /* No need to keep the lock */
9229                         relation_close(seqRel, lockmode);
9230                         continue;
9231                 }
9232
9233                 /* We don't need to close the sequence while we alter it. */
9234                 ATExecChangeOwner(depForm->objid, newOwnerId, true, lockmode);
9235
9236                 /* Now we can close it.  Keep the lock till end of transaction. */
9237                 relation_close(seqRel, NoLock);
9238         }
9239
9240         systable_endscan(scan);
9241
9242         relation_close(depRel, AccessShareLock);
9243 }
9244
9245 /*
9246  * ALTER TABLE CLUSTER ON
9247  *
9248  * The only thing we have to do is to change the indisclustered bits.
9249  *
9250  * Return the address of the new clustering index.
9251  */
9252 static ObjectAddress
9253 ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode)
9254 {
9255         Oid                     indexOid;
9256         ObjectAddress address;
9257
9258         indexOid = get_relname_relid(indexName, rel->rd_rel->relnamespace);
9259
9260         if (!OidIsValid(indexOid))
9261                 ereport(ERROR,
9262                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
9263                                  errmsg("index \"%s\" for table \"%s\" does not exist",
9264                                                 indexName, RelationGetRelationName(rel))));
9265
9266         /* Check index is valid to cluster on */
9267         check_index_is_clusterable(rel, indexOid, false, lockmode);
9268
9269         /* And do the work */
9270         mark_index_clustered(rel, indexOid, false);
9271
9272         ObjectAddressSet(address,
9273                                          RelationRelationId, indexOid);
9274
9275         return address;
9276 }
9277
9278 /*
9279  * ALTER TABLE SET WITHOUT CLUSTER
9280  *
9281  * We have to find any indexes on the table that have indisclustered bit
9282  * set and turn it off.
9283  */
9284 static void
9285 ATExecDropCluster(Relation rel, LOCKMODE lockmode)
9286 {
9287         mark_index_clustered(rel, InvalidOid, false);
9288 }
9289
9290 /*
9291  * ALTER TABLE SET TABLESPACE
9292  */
9293 static void
9294 ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename, LOCKMODE lockmode)
9295 {
9296         Oid                     tablespaceId;
9297
9298         /* Check that the tablespace exists */
9299         tablespaceId = get_tablespace_oid(tablespacename, false);
9300
9301         /* Check permissions except when moving to database's default */
9302         if (OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
9303         {
9304                 AclResult       aclresult;
9305
9306                 aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(), ACL_CREATE);
9307                 if (aclresult != ACLCHECK_OK)
9308                         aclcheck_error(aclresult, ACL_KIND_TABLESPACE, tablespacename);
9309         }
9310
9311         /* Save info for Phase 3 to do the real work */
9312         if (OidIsValid(tab->newTableSpace))
9313                 ereport(ERROR,
9314                                 (errcode(ERRCODE_SYNTAX_ERROR),
9315                                  errmsg("cannot have multiple SET TABLESPACE subcommands")));
9316
9317         tab->newTableSpace = tablespaceId;
9318 }
9319
9320 /*
9321  * Set, reset, or replace reloptions.
9322  */
9323 static void
9324 ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
9325                                         LOCKMODE lockmode)
9326 {
9327         Oid                     relid;
9328         Relation        pgclass;
9329         HeapTuple       tuple;
9330         HeapTuple       newtuple;
9331         Datum           datum;
9332         bool            isnull;
9333         Datum           newOptions;
9334         Datum           repl_val[Natts_pg_class];
9335         bool            repl_null[Natts_pg_class];
9336         bool            repl_repl[Natts_pg_class];
9337         static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
9338
9339         if (defList == NIL && operation != AT_ReplaceRelOptions)
9340                 return;                                 /* nothing to do */
9341
9342         pgclass = heap_open(RelationRelationId, RowExclusiveLock);
9343
9344         /* Fetch heap tuple */
9345         relid = RelationGetRelid(rel);
9346         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
9347         if (!HeapTupleIsValid(tuple))
9348                 elog(ERROR, "cache lookup failed for relation %u", relid);
9349
9350         if (operation == AT_ReplaceRelOptions)
9351         {
9352                 /*
9353                  * If we're supposed to replace the reloptions list, we just pretend
9354                  * there were none before.
9355                  */
9356                 datum = (Datum) 0;
9357                 isnull = true;
9358         }
9359         else
9360         {
9361                 /* Get the old reloptions */
9362                 datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
9363                                                                 &isnull);
9364         }
9365
9366         /* Generate new proposed reloptions (text array) */
9367         newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
9368                                                                          defList, NULL, validnsps, false,
9369                                                                          operation == AT_ResetRelOptions);
9370
9371         /* Validate */
9372         switch (rel->rd_rel->relkind)
9373         {
9374                 case RELKIND_RELATION:
9375                 case RELKIND_TOASTVALUE:
9376                 case RELKIND_MATVIEW:
9377                         (void) heap_reloptions(rel->rd_rel->relkind, newOptions, true);
9378                         break;
9379                 case RELKIND_VIEW:
9380                         (void) view_reloptions(newOptions, true);
9381                         break;
9382                 case RELKIND_INDEX:
9383                         (void) index_reloptions(rel->rd_am->amoptions, newOptions, true);
9384                         break;
9385                 default:
9386                         ereport(ERROR,
9387                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9388                                          errmsg("\"%s\" is not a table, view, materialized view, index, or TOAST table",
9389                                                         RelationGetRelationName(rel))));
9390                         break;
9391         }
9392
9393         /* Special-case validation of view options */
9394         if (rel->rd_rel->relkind == RELKIND_VIEW)
9395         {
9396                 Query      *view_query = get_view_query(rel);
9397                 List       *view_options = untransformRelOptions(newOptions);
9398                 ListCell   *cell;
9399                 bool            check_option = false;
9400
9401                 foreach(cell, view_options)
9402                 {
9403                         DefElem    *defel = (DefElem *) lfirst(cell);
9404
9405                         if (pg_strcasecmp(defel->defname, "check_option") == 0)
9406                                 check_option = true;
9407                 }
9408
9409                 /*
9410                  * If the check option is specified, look to see if the view is
9411                  * actually auto-updatable or not.
9412                  */
9413                 if (check_option)
9414                 {
9415                         const char *view_updatable_error =
9416                         view_query_is_auto_updatable(view_query, true);
9417
9418                         if (view_updatable_error)
9419                                 ereport(ERROR,
9420                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9421                                                  errmsg("WITH CHECK OPTION is supported only on automatically updatable views"),
9422                                                  errhint("%s", view_updatable_error)));
9423                 }
9424         }
9425
9426         /*
9427          * All we need do here is update the pg_class row; the new options will be
9428          * propagated into relcaches during post-commit cache inval.
9429          */
9430         memset(repl_val, 0, sizeof(repl_val));
9431         memset(repl_null, false, sizeof(repl_null));
9432         memset(repl_repl, false, sizeof(repl_repl));
9433
9434         if (newOptions != (Datum) 0)
9435                 repl_val[Anum_pg_class_reloptions - 1] = newOptions;
9436         else
9437                 repl_null[Anum_pg_class_reloptions - 1] = true;
9438
9439         repl_repl[Anum_pg_class_reloptions - 1] = true;
9440
9441         newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass),
9442                                                                  repl_val, repl_null, repl_repl);
9443
9444         simple_heap_update(pgclass, &newtuple->t_self, newtuple);
9445
9446         CatalogUpdateIndexes(pgclass, newtuple);
9447
9448         InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
9449
9450         heap_freetuple(newtuple);
9451
9452         ReleaseSysCache(tuple);
9453
9454         /* repeat the whole exercise for the toast table, if there's one */
9455         if (OidIsValid(rel->rd_rel->reltoastrelid))
9456         {
9457                 Relation        toastrel;
9458                 Oid                     toastid = rel->rd_rel->reltoastrelid;
9459
9460                 toastrel = heap_open(toastid, lockmode);
9461
9462                 /* Fetch heap tuple */
9463                 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(toastid));
9464                 if (!HeapTupleIsValid(tuple))
9465                         elog(ERROR, "cache lookup failed for relation %u", toastid);
9466
9467                 if (operation == AT_ReplaceRelOptions)
9468                 {
9469                         /*
9470                          * If we're supposed to replace the reloptions list, we just
9471                          * pretend there were none before.
9472                          */
9473                         datum = (Datum) 0;
9474                         isnull = true;
9475                 }
9476                 else
9477                 {
9478                         /* Get the old reloptions */
9479                         datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
9480                                                                         &isnull);
9481                 }
9482
9483                 newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
9484                                                                                  defList, "toast", validnsps, false,
9485                                                                                  operation == AT_ResetRelOptions);
9486
9487                 (void) heap_reloptions(RELKIND_TOASTVALUE, newOptions, true);
9488
9489                 memset(repl_val, 0, sizeof(repl_val));
9490                 memset(repl_null, false, sizeof(repl_null));
9491                 memset(repl_repl, false, sizeof(repl_repl));
9492
9493                 if (newOptions != (Datum) 0)
9494                         repl_val[Anum_pg_class_reloptions - 1] = newOptions;
9495                 else
9496                         repl_null[Anum_pg_class_reloptions - 1] = true;
9497
9498                 repl_repl[Anum_pg_class_reloptions - 1] = true;
9499
9500                 newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass),
9501                                                                          repl_val, repl_null, repl_repl);
9502
9503                 simple_heap_update(pgclass, &newtuple->t_self, newtuple);
9504
9505                 CatalogUpdateIndexes(pgclass, newtuple);
9506
9507                 InvokeObjectPostAlterHookArg(RelationRelationId,
9508                                                                          RelationGetRelid(toastrel), 0,
9509                                                                          InvalidOid, true);
9510
9511                 heap_freetuple(newtuple);
9512
9513                 ReleaseSysCache(tuple);
9514
9515                 heap_close(toastrel, NoLock);
9516         }
9517
9518         heap_close(pgclass, RowExclusiveLock);
9519 }
9520
9521 /*
9522  * Execute ALTER TABLE SET TABLESPACE for cases where there is no tuple
9523  * rewriting to be done, so we just want to copy the data as fast as possible.
9524  */
9525 static void
9526 ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
9527 {
9528         Relation        rel;
9529         Oid                     oldTableSpace;
9530         Oid                     reltoastrelid;
9531         Oid                     newrelfilenode;
9532         RelFileNode newrnode;
9533         SMgrRelation dstrel;
9534         Relation        pg_class;
9535         HeapTuple       tuple;
9536         Form_pg_class rd_rel;
9537         ForkNumber      forkNum;
9538         List       *reltoastidxids = NIL;
9539         ListCell   *lc;
9540
9541         /*
9542          * Need lock here in case we are recursing to toast table or index
9543          */
9544         rel = relation_open(tableOid, lockmode);
9545
9546         /*
9547          * No work if no change in tablespace.
9548          */
9549         oldTableSpace = rel->rd_rel->reltablespace;
9550         if (newTableSpace == oldTableSpace ||
9551                 (newTableSpace == MyDatabaseTableSpace && oldTableSpace == 0))
9552         {
9553                 InvokeObjectPostAlterHook(RelationRelationId,
9554                                                                   RelationGetRelid(rel), 0);
9555
9556                 relation_close(rel, NoLock);
9557                 return;
9558         }
9559
9560         /*
9561          * We cannot support moving mapped relations into different tablespaces.
9562          * (In particular this eliminates all shared catalogs.)
9563          */
9564         if (RelationIsMapped(rel))
9565                 ereport(ERROR,
9566                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9567                                  errmsg("cannot move system relation \"%s\"",
9568                                                 RelationGetRelationName(rel))));
9569
9570         /* Can't move a non-shared relation into pg_global */
9571         if (newTableSpace == GLOBALTABLESPACE_OID)
9572                 ereport(ERROR,
9573                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
9574                                  errmsg("only shared relations can be placed in pg_global tablespace")));
9575
9576         /*
9577          * Don't allow moving temp tables of other backends ... their local buffer
9578          * manager is not going to cope.
9579          */
9580         if (RELATION_IS_OTHER_TEMP(rel))
9581                 ereport(ERROR,
9582                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9583                                  errmsg("cannot move temporary tables of other sessions")));
9584
9585         reltoastrelid = rel->rd_rel->reltoastrelid;
9586         /* Fetch the list of indexes on toast relation if necessary */
9587         if (OidIsValid(reltoastrelid))
9588         {
9589                 Relation        toastRel = relation_open(reltoastrelid, lockmode);
9590
9591                 reltoastidxids = RelationGetIndexList(toastRel);
9592                 relation_close(toastRel, lockmode);
9593         }
9594
9595         /* Get a modifiable copy of the relation's pg_class row */
9596         pg_class = heap_open(RelationRelationId, RowExclusiveLock);
9597
9598         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(tableOid));
9599         if (!HeapTupleIsValid(tuple))
9600                 elog(ERROR, "cache lookup failed for relation %u", tableOid);
9601         rd_rel = (Form_pg_class) GETSTRUCT(tuple);
9602
9603         /*
9604          * Since we copy the file directly without looking at the shared buffers,
9605          * we'd better first flush out any pages of the source relation that are
9606          * in shared buffers.  We assume no new changes will be made while we are
9607          * holding exclusive lock on the rel.
9608          */
9609         FlushRelationBuffers(rel);
9610
9611         /*
9612          * Relfilenodes are not unique in databases across tablespaces, so we need
9613          * to allocate a new one in the new tablespace.
9614          */
9615         newrelfilenode = GetNewRelFileNode(newTableSpace, NULL,
9616                                                                            rel->rd_rel->relpersistence);
9617
9618         /* Open old and new relation */
9619         newrnode = rel->rd_node;
9620         newrnode.relNode = newrelfilenode;
9621         newrnode.spcNode = newTableSpace;
9622         dstrel = smgropen(newrnode, rel->rd_backend);
9623
9624         RelationOpenSmgr(rel);
9625
9626         /*
9627          * Create and copy all forks of the relation, and schedule unlinking of
9628          * old physical files.
9629          *
9630          * NOTE: any conflict in relfilenode value will be caught in
9631          * RelationCreateStorage().
9632          */
9633         RelationCreateStorage(newrnode, rel->rd_rel->relpersistence);
9634
9635         /* copy main fork */
9636         copy_relation_data(rel->rd_smgr, dstrel, MAIN_FORKNUM,
9637                                            rel->rd_rel->relpersistence);
9638
9639         /* copy those extra forks that exist */
9640         for (forkNum = MAIN_FORKNUM + 1; forkNum <= MAX_FORKNUM; forkNum++)
9641         {
9642                 if (smgrexists(rel->rd_smgr, forkNum))
9643                 {
9644                         smgrcreate(dstrel, forkNum, false);
9645                         copy_relation_data(rel->rd_smgr, dstrel, forkNum,
9646                                                            rel->rd_rel->relpersistence);
9647                 }
9648         }
9649
9650         /* drop old relation, and close new one */
9651         RelationDropStorage(rel);
9652         smgrclose(dstrel);
9653
9654         /* update the pg_class row */
9655         rd_rel->reltablespace = (newTableSpace == MyDatabaseTableSpace) ? InvalidOid : newTableSpace;
9656         rd_rel->relfilenode = newrelfilenode;
9657         simple_heap_update(pg_class, &tuple->t_self, tuple);
9658         CatalogUpdateIndexes(pg_class, tuple);
9659
9660         InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
9661
9662         heap_freetuple(tuple);
9663
9664         heap_close(pg_class, RowExclusiveLock);
9665
9666         relation_close(rel, NoLock);
9667
9668         /* Make sure the reltablespace change is visible */
9669         CommandCounterIncrement();
9670
9671         /* Move associated toast relation and/or indexes, too */
9672         if (OidIsValid(reltoastrelid))
9673                 ATExecSetTableSpace(reltoastrelid, newTableSpace, lockmode);
9674         foreach(lc, reltoastidxids)
9675                 ATExecSetTableSpace(lfirst_oid(lc), newTableSpace, lockmode);
9676
9677         /* Clean up */
9678         list_free(reltoastidxids);
9679 }
9680
9681 /*
9682  * Alter Table ALL ... SET TABLESPACE
9683  *
9684  * Allows a user to move all objects of some type in a given tablespace in the
9685  * current database to another tablespace.  Objects can be chosen based on the
9686  * owner of the object also, to allow users to move only their objects.
9687  * The user must have CREATE rights on the new tablespace, as usual.   The main
9688  * permissions handling is done by the lower-level table move function.
9689  *
9690  * All to-be-moved objects are locked first. If NOWAIT is specified and the
9691  * lock can't be acquired then we ereport(ERROR).
9692  */
9693 Oid
9694 AlterTableMoveAll(AlterTableMoveAllStmt *stmt)
9695 {
9696         List       *relations = NIL;
9697         ListCell   *l;
9698         ScanKeyData key[1];
9699         Relation        rel;
9700         HeapScanDesc scan;
9701         HeapTuple       tuple;
9702         Oid                     orig_tablespaceoid;
9703         Oid                     new_tablespaceoid;
9704         List       *role_oids = roleSpecsToIds(stmt->roles);
9705
9706         /* Ensure we were not asked to move something we can't */
9707         if (stmt->objtype != OBJECT_TABLE && stmt->objtype != OBJECT_INDEX &&
9708                 stmt->objtype != OBJECT_MATVIEW)
9709                 ereport(ERROR,
9710                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
9711                                  errmsg("only tables, indexes, and materialized views exist in tablespaces")));
9712
9713         /* Get the orig and new tablespace OIDs */
9714         orig_tablespaceoid = get_tablespace_oid(stmt->orig_tablespacename, false);
9715         new_tablespaceoid = get_tablespace_oid(stmt->new_tablespacename, false);
9716
9717         /* Can't move shared relations in to or out of pg_global */
9718         /* This is also checked by ATExecSetTableSpace, but nice to stop earlier */
9719         if (orig_tablespaceoid == GLOBALTABLESPACE_OID ||
9720                 new_tablespaceoid == GLOBALTABLESPACE_OID)
9721                 ereport(ERROR,
9722                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
9723                                  errmsg("cannot move relations in to or out of pg_global tablespace")));
9724
9725         /*
9726          * Must have CREATE rights on the new tablespace, unless it is the
9727          * database default tablespace (which all users implicitly have CREATE
9728          * rights on).
9729          */
9730         if (OidIsValid(new_tablespaceoid) && new_tablespaceoid != MyDatabaseTableSpace)
9731         {
9732                 AclResult       aclresult;
9733
9734                 aclresult = pg_tablespace_aclcheck(new_tablespaceoid, GetUserId(),
9735                                                                                    ACL_CREATE);
9736                 if (aclresult != ACLCHECK_OK)
9737                         aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
9738                                                    get_tablespace_name(new_tablespaceoid));
9739         }
9740
9741         /*
9742          * Now that the checks are done, check if we should set either to
9743          * InvalidOid because it is our database's default tablespace.
9744          */
9745         if (orig_tablespaceoid == MyDatabaseTableSpace)
9746                 orig_tablespaceoid = InvalidOid;
9747
9748         if (new_tablespaceoid == MyDatabaseTableSpace)
9749                 new_tablespaceoid = InvalidOid;
9750
9751         /* no-op */
9752         if (orig_tablespaceoid == new_tablespaceoid)
9753                 return new_tablespaceoid;
9754
9755         /*
9756          * Walk the list of objects in the tablespace and move them. This will
9757          * only find objects in our database, of course.
9758          */
9759         ScanKeyInit(&key[0],
9760                                 Anum_pg_class_reltablespace,
9761                                 BTEqualStrategyNumber, F_OIDEQ,
9762                                 ObjectIdGetDatum(orig_tablespaceoid));
9763
9764         rel = heap_open(RelationRelationId, AccessShareLock);
9765         scan = heap_beginscan_catalog(rel, 1, key);
9766         while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
9767         {
9768                 Oid                     relOid = HeapTupleGetOid(tuple);
9769                 Form_pg_class relForm;
9770
9771                 relForm = (Form_pg_class) GETSTRUCT(tuple);
9772
9773                 /*
9774                  * Do not move objects in pg_catalog as part of this, if an admin
9775                  * really wishes to do so, they can issue the individual ALTER
9776                  * commands directly.
9777                  *
9778                  * Also, explicitly avoid any shared tables, temp tables, or TOAST
9779                  * (TOAST will be moved with the main table).
9780                  */
9781                 if (IsSystemNamespace(relForm->relnamespace) || relForm->relisshared ||
9782                         isAnyTempNamespace(relForm->relnamespace) ||
9783                         relForm->relnamespace == PG_TOAST_NAMESPACE)
9784                         continue;
9785
9786                 /* Only move the object type requested */
9787                 if ((stmt->objtype == OBJECT_TABLE &&
9788                          relForm->relkind != RELKIND_RELATION) ||
9789                         (stmt->objtype == OBJECT_INDEX &&
9790                          relForm->relkind != RELKIND_INDEX) ||
9791                         (stmt->objtype == OBJECT_MATVIEW &&
9792                          relForm->relkind != RELKIND_MATVIEW))
9793                         continue;
9794
9795                 /* Check if we are only moving objects owned by certain roles */
9796                 if (role_oids != NIL && !list_member_oid(role_oids, relForm->relowner))
9797                         continue;
9798
9799                 /*
9800                  * Handle permissions-checking here since we are locking the tables
9801                  * and also to avoid doing a bunch of work only to fail part-way. Note
9802                  * that permissions will also be checked by AlterTableInternal().
9803                  *
9804                  * Caller must be considered an owner on the table to move it.
9805                  */
9806                 if (!pg_class_ownercheck(relOid, GetUserId()))
9807                         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
9808                                                    NameStr(relForm->relname));
9809
9810                 if (stmt->nowait &&
9811                         !ConditionalLockRelationOid(relOid, AccessExclusiveLock))
9812                         ereport(ERROR,
9813                                         (errcode(ERRCODE_OBJECT_IN_USE),
9814                                          errmsg("aborting because lock on relation \"%s\".\"%s\" is not available",
9815                                                         get_namespace_name(relForm->relnamespace),
9816                                                         NameStr(relForm->relname))));
9817                 else
9818                         LockRelationOid(relOid, AccessExclusiveLock);
9819
9820                 /* Add to our list of objects to move */
9821                 relations = lappend_oid(relations, relOid);
9822         }
9823
9824         heap_endscan(scan);
9825         heap_close(rel, AccessShareLock);
9826
9827         if (relations == NIL)
9828                 ereport(NOTICE,
9829                                 (errcode(ERRCODE_NO_DATA_FOUND),
9830                                  errmsg("no matching relations in tablespace \"%s\" found",
9831                                         orig_tablespaceoid == InvalidOid ? "(database default)" :
9832                                                 get_tablespace_name(orig_tablespaceoid))));
9833
9834         /* Everything is locked, loop through and move all of the relations. */
9835         foreach(l, relations)
9836         {
9837                 List       *cmds = NIL;
9838                 AlterTableCmd *cmd = makeNode(AlterTableCmd);
9839
9840                 cmd->subtype = AT_SetTableSpace;
9841                 cmd->name = stmt->new_tablespacename;
9842
9843                 cmds = lappend(cmds, cmd);
9844
9845                 EventTriggerAlterTableStart((Node *) stmt);
9846                 /* OID is set by AlterTableInternal */
9847                 AlterTableInternal(lfirst_oid(l), cmds, false);
9848                 EventTriggerAlterTableEnd();
9849         }
9850
9851         return new_tablespaceoid;
9852 }
9853
9854 /*
9855  * Copy data, block by block
9856  */
9857 static void
9858 copy_relation_data(SMgrRelation src, SMgrRelation dst,
9859                                    ForkNumber forkNum, char relpersistence)
9860 {
9861         char       *buf;
9862         Page            page;
9863         bool            use_wal;
9864         BlockNumber nblocks;
9865         BlockNumber blkno;
9866
9867         /*
9868          * palloc the buffer so that it's MAXALIGN'd.  If it were just a local
9869          * char[] array, the compiler might align it on any byte boundary, which
9870          * can seriously hurt transfer speed to and from the kernel; not to
9871          * mention possibly making log_newpage's accesses to the page header fail.
9872          */
9873         buf = (char *) palloc(BLCKSZ);
9874         page = (Page) buf;
9875
9876         /*
9877          * We need to log the copied data in WAL iff WAL archiving/streaming is
9878          * enabled AND it's a permanent relation.
9879          */
9880         use_wal = XLogIsNeeded() && relpersistence == RELPERSISTENCE_PERMANENT;
9881
9882         nblocks = smgrnblocks(src, forkNum);
9883
9884         for (blkno = 0; blkno < nblocks; blkno++)
9885         {
9886                 /* If we got a cancel signal during the copy of the data, quit */
9887                 CHECK_FOR_INTERRUPTS();
9888
9889                 smgrread(src, forkNum, blkno, buf);
9890
9891                 if (!PageIsVerified(page, blkno))
9892                         ereport(ERROR,
9893                                         (errcode(ERRCODE_DATA_CORRUPTED),
9894                                          errmsg("invalid page in block %u of relation %s",
9895                                                         blkno,
9896                                                         relpathbackend(src->smgr_rnode.node,
9897                                                                                    src->smgr_rnode.backend,
9898                                                                                    forkNum))));
9899
9900                 /*
9901                  * WAL-log the copied page. Unfortunately we don't know what kind of a
9902                  * page this is, so we have to log the full page including any unused
9903                  * space.
9904                  */
9905                 if (use_wal)
9906                         log_newpage(&dst->smgr_rnode.node, forkNum, blkno, page, false);
9907
9908                 PageSetChecksumInplace(page, blkno);
9909
9910                 /*
9911                  * Now write the page.  We say isTemp = true even if it's not a temp
9912                  * rel, because there's no need for smgr to schedule an fsync for this
9913                  * write; we'll do it ourselves below.
9914                  */
9915                 smgrextend(dst, forkNum, blkno, buf, true);
9916         }
9917
9918         pfree(buf);
9919
9920         /*
9921          * If the rel is WAL-logged, must fsync before commit.  We use heap_sync
9922          * to ensure that the toast table gets fsync'd too.  (For a temp or
9923          * unlogged rel we don't care since the data will be gone after a crash
9924          * anyway.)
9925          *
9926          * It's obvious that we must do this when not WAL-logging the copy. It's
9927          * less obvious that we have to do it even if we did WAL-log the copied
9928          * pages. The reason is that since we're copying outside shared buffers, a
9929          * CHECKPOINT occurring during the copy has no way to flush the previously
9930          * written data to disk (indeed it won't know the new rel even exists).  A
9931          * crash later on would replay WAL from the checkpoint, therefore it
9932          * wouldn't replay our earlier WAL entries. If we do not fsync those pages
9933          * here, they might still not be on disk when the crash occurs.
9934          */
9935         if (relpersistence == RELPERSISTENCE_PERMANENT)
9936                 smgrimmedsync(dst, forkNum);
9937 }
9938
9939 /*
9940  * ALTER TABLE ENABLE/DISABLE TRIGGER
9941  *
9942  * We just pass this off to trigger.c.
9943  */
9944 static void
9945 ATExecEnableDisableTrigger(Relation rel, char *trigname,
9946                                                 char fires_when, bool skip_system, LOCKMODE lockmode)
9947 {
9948         EnableDisableTrigger(rel, trigname, fires_when, skip_system);
9949 }
9950
9951 /*
9952  * ALTER TABLE ENABLE/DISABLE RULE
9953  *
9954  * We just pass this off to rewriteDefine.c.
9955  */
9956 static void
9957 ATExecEnableDisableRule(Relation rel, char *trigname,
9958                                                 char fires_when, LOCKMODE lockmode)
9959 {
9960         EnableDisableRule(rel, trigname, fires_when);
9961 }
9962
9963 /*
9964  * ALTER TABLE INHERIT
9965  *
9966  * Add a parent to the child's parents. This verifies that all the columns and
9967  * check constraints of the parent appear in the child and that they have the
9968  * same data types and expressions.
9969  */
9970 static void
9971 ATPrepAddInherit(Relation child_rel)
9972 {
9973         if (child_rel->rd_rel->reloftype)
9974                 ereport(ERROR,
9975                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
9976                                  errmsg("cannot change inheritance of typed table")));
9977 }
9978
9979 /*
9980  * Return the address of the new parent relation.
9981  */
9982 static ObjectAddress
9983 ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
9984 {
9985         Relation        parent_rel,
9986                                 catalogRelation;
9987         SysScanDesc scan;
9988         ScanKeyData key;
9989         HeapTuple       inheritsTuple;
9990         int32           inhseqno;
9991         List       *children;
9992         ObjectAddress address;
9993
9994         /*
9995          * A self-exclusive lock is needed here.  See the similar case in
9996          * MergeAttributes() for a full explanation.
9997          */
9998         parent_rel = heap_openrv(parent, ShareUpdateExclusiveLock);
9999
10000         /*
10001          * Must be owner of both parent and child -- child was checked by
10002          * ATSimplePermissions call in ATPrepCmd
10003          */
10004         ATSimplePermissions(parent_rel, ATT_TABLE | ATT_FOREIGN_TABLE);
10005
10006         /* Permanent rels cannot inherit from temporary ones */
10007         if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
10008                 child_rel->rd_rel->relpersistence != RELPERSISTENCE_TEMP)
10009                 ereport(ERROR,
10010                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10011                                  errmsg("cannot inherit from temporary relation \"%s\"",
10012                                                 RelationGetRelationName(parent_rel))));
10013
10014         /* If parent rel is temp, it must belong to this session */
10015         if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
10016                 !parent_rel->rd_islocaltemp)
10017                 ereport(ERROR,
10018                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10019                 errmsg("cannot inherit from temporary relation of another session")));
10020
10021         /* Ditto for the child */
10022         if (child_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
10023                 !child_rel->rd_islocaltemp)
10024                 ereport(ERROR,
10025                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10026                  errmsg("cannot inherit to temporary relation of another session")));
10027
10028         /*
10029          * Check for duplicates in the list of parents, and determine the highest
10030          * inhseqno already present; we'll use the next one for the new parent.
10031          * (Note: get RowExclusiveLock because we will write pg_inherits below.)
10032          *
10033          * Note: we do not reject the case where the child already inherits from
10034          * the parent indirectly; CREATE TABLE doesn't reject comparable cases.
10035          */
10036         catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
10037         ScanKeyInit(&key,
10038                                 Anum_pg_inherits_inhrelid,
10039                                 BTEqualStrategyNumber, F_OIDEQ,
10040                                 ObjectIdGetDatum(RelationGetRelid(child_rel)));
10041         scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
10042                                                           true, NULL, 1, &key);
10043
10044         /* inhseqno sequences start at 1 */
10045         inhseqno = 0;
10046         while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
10047         {
10048                 Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inheritsTuple);
10049
10050                 if (inh->inhparent == RelationGetRelid(parent_rel))
10051                         ereport(ERROR,
10052                                         (errcode(ERRCODE_DUPLICATE_TABLE),
10053                          errmsg("relation \"%s\" would be inherited from more than once",
10054                                         RelationGetRelationName(parent_rel))));
10055                 if (inh->inhseqno > inhseqno)
10056                         inhseqno = inh->inhseqno;
10057         }
10058         systable_endscan(scan);
10059
10060         /*
10061          * Prevent circularity by seeing if proposed parent inherits from child.
10062          * (In particular, this disallows making a rel inherit from itself.)
10063          *
10064          * This is not completely bulletproof because of race conditions: in
10065          * multi-level inheritance trees, someone else could concurrently be
10066          * making another inheritance link that closes the loop but does not join
10067          * either of the rels we have locked.  Preventing that seems to require
10068          * exclusive locks on the entire inheritance tree, which is a cure worse
10069          * than the disease.  find_all_inheritors() will cope with circularity
10070          * anyway, so don't sweat it too much.
10071          *
10072          * We use weakest lock we can on child's children, namely AccessShareLock.
10073          */
10074         children = find_all_inheritors(RelationGetRelid(child_rel),
10075                                                                    AccessShareLock, NULL);
10076
10077         if (list_member_oid(children, RelationGetRelid(parent_rel)))
10078                 ereport(ERROR,
10079                                 (errcode(ERRCODE_DUPLICATE_TABLE),
10080                                  errmsg("circular inheritance not allowed"),
10081                                  errdetail("\"%s\" is already a child of \"%s\".",
10082                                                    parent->relname,
10083                                                    RelationGetRelationName(child_rel))));
10084
10085         /* If parent has OIDs then child must have OIDs */
10086         if (parent_rel->rd_rel->relhasoids && !child_rel->rd_rel->relhasoids)
10087                 ereport(ERROR,
10088                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10089                                  errmsg("table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs",
10090                                                 RelationGetRelationName(child_rel),
10091                                                 RelationGetRelationName(parent_rel))));
10092
10093         /* Match up the columns and bump attinhcount as needed */
10094         MergeAttributesIntoExisting(child_rel, parent_rel);
10095
10096         /* Match up the constraints and bump coninhcount as needed */
10097         MergeConstraintsIntoExisting(child_rel, parent_rel);
10098
10099         /*
10100          * OK, it looks valid.  Make the catalog entries that show inheritance.
10101          */
10102         StoreCatalogInheritance1(RelationGetRelid(child_rel),
10103                                                          RelationGetRelid(parent_rel),
10104                                                          inhseqno + 1,
10105                                                          catalogRelation);
10106
10107         ObjectAddressSet(address, RelationRelationId,
10108                                          RelationGetRelid(parent_rel));
10109
10110         /* Now we're done with pg_inherits */
10111         heap_close(catalogRelation, RowExclusiveLock);
10112
10113         /* keep our lock on the parent relation until commit */
10114         heap_close(parent_rel, NoLock);
10115
10116         return address;
10117 }
10118
10119 /*
10120  * Obtain the source-text form of the constraint expression for a check
10121  * constraint, given its pg_constraint tuple
10122  */
10123 static char *
10124 decompile_conbin(HeapTuple contup, TupleDesc tupdesc)
10125 {
10126         Form_pg_constraint con;
10127         bool            isnull;
10128         Datum           attr;
10129         Datum           expr;
10130
10131         con = (Form_pg_constraint) GETSTRUCT(contup);
10132         attr = heap_getattr(contup, Anum_pg_constraint_conbin, tupdesc, &isnull);
10133         if (isnull)
10134                 elog(ERROR, "null conbin for constraint %u", HeapTupleGetOid(contup));
10135
10136         expr = DirectFunctionCall2(pg_get_expr, attr,
10137                                                            ObjectIdGetDatum(con->conrelid));
10138         return TextDatumGetCString(expr);
10139 }
10140
10141 /*
10142  * Determine whether two check constraints are functionally equivalent
10143  *
10144  * The test we apply is to see whether they reverse-compile to the same
10145  * source string.  This insulates us from issues like whether attributes
10146  * have the same physical column numbers in parent and child relations.
10147  */
10148 static bool
10149 constraints_equivalent(HeapTuple a, HeapTuple b, TupleDesc tupleDesc)
10150 {
10151         Form_pg_constraint acon = (Form_pg_constraint) GETSTRUCT(a);
10152         Form_pg_constraint bcon = (Form_pg_constraint) GETSTRUCT(b);
10153
10154         if (acon->condeferrable != bcon->condeferrable ||
10155                 acon->condeferred != bcon->condeferred ||
10156                 strcmp(decompile_conbin(a, tupleDesc),
10157                            decompile_conbin(b, tupleDesc)) != 0)
10158                 return false;
10159         else
10160                 return true;
10161 }
10162
10163 /*
10164  * Check columns in child table match up with columns in parent, and increment
10165  * their attinhcount.
10166  *
10167  * Called by ATExecAddInherit
10168  *
10169  * Currently all parent columns must be found in child. Missing columns are an
10170  * error.  One day we might consider creating new columns like CREATE TABLE
10171  * does.  However, that is widely unpopular --- in the common use case of
10172  * partitioned tables it's a foot-gun.
10173  *
10174  * The data type must match exactly. If the parent column is NOT NULL then
10175  * the child must be as well. Defaults are not compared, however.
10176  */
10177 static void
10178 MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
10179 {
10180         Relation        attrrel;
10181         AttrNumber      parent_attno;
10182         int                     parent_natts;
10183         TupleDesc       tupleDesc;
10184         HeapTuple       tuple;
10185
10186         attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
10187
10188         tupleDesc = RelationGetDescr(parent_rel);
10189         parent_natts = tupleDesc->natts;
10190
10191         for (parent_attno = 1; parent_attno <= parent_natts; parent_attno++)
10192         {
10193                 Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
10194                 char       *attributeName = NameStr(attribute->attname);
10195
10196                 /* Ignore dropped columns in the parent. */
10197                 if (attribute->attisdropped)
10198                         continue;
10199
10200                 /* Find same column in child (matching on column name). */
10201                 tuple = SearchSysCacheCopyAttName(RelationGetRelid(child_rel),
10202                                                                                   attributeName);
10203                 if (HeapTupleIsValid(tuple))
10204                 {
10205                         /* Check they are same type, typmod, and collation */
10206                         Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
10207
10208                         if (attribute->atttypid != childatt->atttypid ||
10209                                 attribute->atttypmod != childatt->atttypmod)
10210                                 ereport(ERROR,
10211                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
10212                                                  errmsg("child table \"%s\" has different type for column \"%s\"",
10213                                                                 RelationGetRelationName(child_rel),
10214                                                                 attributeName)));
10215
10216                         if (attribute->attcollation != childatt->attcollation)
10217                                 ereport(ERROR,
10218                                                 (errcode(ERRCODE_COLLATION_MISMATCH),
10219                                                  errmsg("child table \"%s\" has different collation for column \"%s\"",
10220                                                                 RelationGetRelationName(child_rel),
10221                                                                 attributeName)));
10222
10223                         /*
10224                          * Check child doesn't discard NOT NULL property.  (Other
10225                          * constraints are checked elsewhere.)
10226                          */
10227                         if (attribute->attnotnull && !childatt->attnotnull)
10228                                 ereport(ERROR,
10229                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
10230                                 errmsg("column \"%s\" in child table must be marked NOT NULL",
10231                                            attributeName)));
10232
10233                         /*
10234                          * OK, bump the child column's inheritance count.  (If we fail
10235                          * later on, this change will just roll back.)
10236                          */
10237                         childatt->attinhcount++;
10238                         simple_heap_update(attrrel, &tuple->t_self, tuple);
10239                         CatalogUpdateIndexes(attrrel, tuple);
10240                         heap_freetuple(tuple);
10241                 }
10242                 else
10243                 {
10244                         ereport(ERROR,
10245                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
10246                                          errmsg("child table is missing column \"%s\"",
10247                                                         attributeName)));
10248                 }
10249         }
10250
10251         heap_close(attrrel, RowExclusiveLock);
10252 }
10253
10254 /*
10255  * Check constraints in child table match up with constraints in parent,
10256  * and increment their coninhcount.
10257  *
10258  * Constraints that are marked ONLY in the parent are ignored.
10259  *
10260  * Called by ATExecAddInherit
10261  *
10262  * Currently all constraints in parent must be present in the child. One day we
10263  * may consider adding new constraints like CREATE TABLE does.
10264  *
10265  * XXX This is O(N^2) which may be an issue with tables with hundreds of
10266  * constraints. As long as tables have more like 10 constraints it shouldn't be
10267  * a problem though. Even 100 constraints ought not be the end of the world.
10268  *
10269  * XXX See MergeWithExistingConstraint too if you change this code.
10270  */
10271 static void
10272 MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
10273 {
10274         Relation        catalog_relation;
10275         TupleDesc       tuple_desc;
10276         SysScanDesc parent_scan;
10277         ScanKeyData parent_key;
10278         HeapTuple       parent_tuple;
10279
10280         catalog_relation = heap_open(ConstraintRelationId, RowExclusiveLock);
10281         tuple_desc = RelationGetDescr(catalog_relation);
10282
10283         /* Outer loop scans through the parent's constraint definitions */
10284         ScanKeyInit(&parent_key,
10285                                 Anum_pg_constraint_conrelid,
10286                                 BTEqualStrategyNumber, F_OIDEQ,
10287                                 ObjectIdGetDatum(RelationGetRelid(parent_rel)));
10288         parent_scan = systable_beginscan(catalog_relation, ConstraintRelidIndexId,
10289                                                                          true, NULL, 1, &parent_key);
10290
10291         while (HeapTupleIsValid(parent_tuple = systable_getnext(parent_scan)))
10292         {
10293                 Form_pg_constraint parent_con = (Form_pg_constraint) GETSTRUCT(parent_tuple);
10294                 SysScanDesc child_scan;
10295                 ScanKeyData child_key;
10296                 HeapTuple       child_tuple;
10297                 bool            found = false;
10298
10299                 if (parent_con->contype != CONSTRAINT_CHECK)
10300                         continue;
10301
10302                 /* if the parent's constraint is marked NO INHERIT, it's not inherited */
10303                 if (parent_con->connoinherit)
10304                         continue;
10305
10306                 /* Search for a child constraint matching this one */
10307                 ScanKeyInit(&child_key,
10308                                         Anum_pg_constraint_conrelid,
10309                                         BTEqualStrategyNumber, F_OIDEQ,
10310                                         ObjectIdGetDatum(RelationGetRelid(child_rel)));
10311                 child_scan = systable_beginscan(catalog_relation, ConstraintRelidIndexId,
10312                                                                                 true, NULL, 1, &child_key);
10313
10314                 while (HeapTupleIsValid(child_tuple = systable_getnext(child_scan)))
10315                 {
10316                         Form_pg_constraint child_con = (Form_pg_constraint) GETSTRUCT(child_tuple);
10317                         HeapTuple       child_copy;
10318
10319                         if (child_con->contype != CONSTRAINT_CHECK)
10320                                 continue;
10321
10322                         if (strcmp(NameStr(parent_con->conname),
10323                                            NameStr(child_con->conname)) != 0)
10324                                 continue;
10325
10326                         if (!constraints_equivalent(parent_tuple, child_tuple, tuple_desc))
10327                                 ereport(ERROR,
10328                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
10329                                                  errmsg("child table \"%s\" has different definition for check constraint \"%s\"",
10330                                                                 RelationGetRelationName(child_rel),
10331                                                                 NameStr(parent_con->conname))));
10332
10333                         /* If the constraint is "no inherit" then cannot merge */
10334                         if (child_con->connoinherit)
10335                                 ereport(ERROR,
10336                                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
10337                                                  errmsg("constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"",
10338                                                                 NameStr(child_con->conname),
10339                                                                 RelationGetRelationName(child_rel))));
10340
10341                         /*
10342                          * OK, bump the child constraint's inheritance count.  (If we fail
10343                          * later on, this change will just roll back.)
10344                          */
10345                         child_copy = heap_copytuple(child_tuple);
10346                         child_con = (Form_pg_constraint) GETSTRUCT(child_copy);
10347                         child_con->coninhcount++;
10348                         simple_heap_update(catalog_relation, &child_copy->t_self, child_copy);
10349                         CatalogUpdateIndexes(catalog_relation, child_copy);
10350                         heap_freetuple(child_copy);
10351
10352                         found = true;
10353                         break;
10354                 }
10355
10356                 systable_endscan(child_scan);
10357
10358                 if (!found)
10359                         ereport(ERROR,
10360                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
10361                                          errmsg("child table is missing constraint \"%s\"",
10362                                                         NameStr(parent_con->conname))));
10363         }
10364
10365         systable_endscan(parent_scan);
10366         heap_close(catalog_relation, RowExclusiveLock);
10367 }
10368
10369 /*
10370  * ALTER TABLE NO INHERIT
10371  *
10372  * Drop a parent from the child's parents. This just adjusts the attinhcount
10373  * and attislocal of the columns and removes the pg_inherit and pg_depend
10374  * entries.
10375  *
10376  * If attinhcount goes to 0 then attislocal gets set to true. If it goes back
10377  * up attislocal stays true, which means if a child is ever removed from a
10378  * parent then its columns will never be automatically dropped which may
10379  * surprise. But at least we'll never surprise by dropping columns someone
10380  * isn't expecting to be dropped which would actually mean data loss.
10381  *
10382  * coninhcount and conislocal for inherited constraints are adjusted in
10383  * exactly the same way.
10384  *
10385  * Return value is the address of the relation that is no longer parent.
10386  */
10387 static ObjectAddress
10388 ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
10389 {
10390         Relation        parent_rel;
10391         Oid                     parent_oid;
10392         Relation        catalogRelation;
10393         SysScanDesc scan;
10394         ScanKeyData key[3];
10395         HeapTuple       inheritsTuple,
10396                                 attributeTuple,
10397                                 constraintTuple;
10398         List       *connames;
10399         bool            found = false;
10400         ObjectAddress address;
10401
10402         /*
10403          * AccessShareLock on the parent is probably enough, seeing that DROP
10404          * TABLE doesn't lock parent tables at all.  We need some lock since we'll
10405          * be inspecting the parent's schema.
10406          */
10407         parent_rel = heap_openrv(parent, AccessShareLock);
10408
10409         /*
10410          * We don't bother to check ownership of the parent table --- ownership of
10411          * the child is presumed enough rights.
10412          */
10413
10414         /*
10415          * Find and destroy the pg_inherits entry linking the two, or error out if
10416          * there is none.
10417          */
10418         catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
10419         ScanKeyInit(&key[0],
10420                                 Anum_pg_inherits_inhrelid,
10421                                 BTEqualStrategyNumber, F_OIDEQ,
10422                                 ObjectIdGetDatum(RelationGetRelid(rel)));
10423         scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
10424                                                           true, NULL, 1, key);
10425
10426         while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
10427         {
10428                 Oid                     inhparent;
10429
10430                 inhparent = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhparent;
10431                 if (inhparent == RelationGetRelid(parent_rel))
10432                 {
10433                         simple_heap_delete(catalogRelation, &inheritsTuple->t_self);
10434                         found = true;
10435                         break;
10436                 }
10437         }
10438
10439         systable_endscan(scan);
10440         heap_close(catalogRelation, RowExclusiveLock);
10441
10442         if (!found)
10443                 ereport(ERROR,
10444                                 (errcode(ERRCODE_UNDEFINED_TABLE),
10445                                  errmsg("relation \"%s\" is not a parent of relation \"%s\"",
10446                                                 RelationGetRelationName(parent_rel),
10447                                                 RelationGetRelationName(rel))));
10448
10449         /*
10450          * Search through child columns looking for ones matching parent rel
10451          */
10452         catalogRelation = heap_open(AttributeRelationId, RowExclusiveLock);
10453         ScanKeyInit(&key[0],
10454                                 Anum_pg_attribute_attrelid,
10455                                 BTEqualStrategyNumber, F_OIDEQ,
10456                                 ObjectIdGetDatum(RelationGetRelid(rel)));
10457         scan = systable_beginscan(catalogRelation, AttributeRelidNumIndexId,
10458                                                           true, NULL, 1, key);
10459         while (HeapTupleIsValid(attributeTuple = systable_getnext(scan)))
10460         {
10461                 Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple);
10462
10463                 /* Ignore if dropped or not inherited */
10464                 if (att->attisdropped)
10465                         continue;
10466                 if (att->attinhcount <= 0)
10467                         continue;
10468
10469                 if (SearchSysCacheExistsAttName(RelationGetRelid(parent_rel),
10470                                                                                 NameStr(att->attname)))
10471                 {
10472                         /* Decrement inhcount and possibly set islocal to true */
10473                         HeapTuple       copyTuple = heap_copytuple(attributeTuple);
10474                         Form_pg_attribute copy_att = (Form_pg_attribute) GETSTRUCT(copyTuple);
10475
10476                         copy_att->attinhcount--;
10477                         if (copy_att->attinhcount == 0)
10478                                 copy_att->attislocal = true;
10479
10480                         simple_heap_update(catalogRelation, &copyTuple->t_self, copyTuple);
10481                         CatalogUpdateIndexes(catalogRelation, copyTuple);
10482                         heap_freetuple(copyTuple);
10483                 }
10484         }
10485         systable_endscan(scan);
10486         heap_close(catalogRelation, RowExclusiveLock);
10487
10488         /*
10489          * Likewise, find inherited check constraints and disinherit them. To do
10490          * this, we first need a list of the names of the parent's check
10491          * constraints.  (We cheat a bit by only checking for name matches,
10492          * assuming that the expressions will match.)
10493          */
10494         catalogRelation = heap_open(ConstraintRelationId, RowExclusiveLock);
10495         ScanKeyInit(&key[0],
10496                                 Anum_pg_constraint_conrelid,
10497                                 BTEqualStrategyNumber, F_OIDEQ,
10498                                 ObjectIdGetDatum(RelationGetRelid(parent_rel)));
10499         scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
10500                                                           true, NULL, 1, key);
10501
10502         connames = NIL;
10503
10504         while (HeapTupleIsValid(constraintTuple = systable_getnext(scan)))
10505         {
10506                 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTuple);
10507
10508                 if (con->contype == CONSTRAINT_CHECK)
10509                         connames = lappend(connames, pstrdup(NameStr(con->conname)));
10510         }
10511
10512         systable_endscan(scan);
10513
10514         /* Now scan the child's constraints */
10515         ScanKeyInit(&key[0],
10516                                 Anum_pg_constraint_conrelid,
10517                                 BTEqualStrategyNumber, F_OIDEQ,
10518                                 ObjectIdGetDatum(RelationGetRelid(rel)));
10519         scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
10520                                                           true, NULL, 1, key);
10521
10522         while (HeapTupleIsValid(constraintTuple = systable_getnext(scan)))
10523         {
10524                 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTuple);
10525                 bool            match;
10526                 ListCell   *lc;
10527
10528                 if (con->contype != CONSTRAINT_CHECK)
10529                         continue;
10530
10531                 match = false;
10532                 foreach(lc, connames)
10533                 {
10534                         if (strcmp(NameStr(con->conname), (char *) lfirst(lc)) == 0)
10535                         {
10536                                 match = true;
10537                                 break;
10538                         }
10539                 }
10540
10541                 if (match)
10542                 {
10543                         /* Decrement inhcount and possibly set islocal to true */
10544                         HeapTuple       copyTuple = heap_copytuple(constraintTuple);
10545                         Form_pg_constraint copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
10546
10547                         if (copy_con->coninhcount <= 0)         /* shouldn't happen */
10548                                 elog(ERROR, "relation %u has non-inherited constraint \"%s\"",
10549                                          RelationGetRelid(rel), NameStr(copy_con->conname));
10550
10551                         copy_con->coninhcount--;
10552                         if (copy_con->coninhcount == 0)
10553                                 copy_con->conislocal = true;
10554
10555                         simple_heap_update(catalogRelation, &copyTuple->t_self, copyTuple);
10556                         CatalogUpdateIndexes(catalogRelation, copyTuple);
10557                         heap_freetuple(copyTuple);
10558                 }
10559         }
10560
10561         parent_oid = RelationGetRelid(parent_rel);
10562
10563         systable_endscan(scan);
10564         heap_close(catalogRelation, RowExclusiveLock);
10565
10566         drop_parent_dependency(RelationGetRelid(rel),
10567                                                    RelationRelationId,
10568                                                    RelationGetRelid(parent_rel));
10569
10570         /*
10571          * Post alter hook of this inherits. Since object_access_hook doesn't take
10572          * multiple object identifiers, we relay oid of parent relation using
10573          * auxiliary_id argument.
10574          */
10575         InvokeObjectPostAlterHookArg(InheritsRelationId,
10576                                                                  RelationGetRelid(rel), 0,
10577                                                                  RelationGetRelid(parent_rel), false);
10578
10579         /* keep our lock on the parent relation until commit */
10580         heap_close(parent_rel, NoLock);
10581
10582         ObjectAddressSet(address, RelationRelationId, parent_oid);
10583
10584         return address;
10585 }
10586
10587 /*
10588  * Drop the dependency created by StoreCatalogInheritance1 (CREATE TABLE
10589  * INHERITS/ALTER TABLE INHERIT -- refclassid will be RelationRelationId) or
10590  * heap_create_with_catalog (CREATE TABLE OF/ALTER TABLE OF -- refclassid will
10591  * be TypeRelationId).  There's no convenient way to do this, so go trawling
10592  * through pg_depend.
10593  */
10594 static void
10595 drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid)
10596 {
10597         Relation        catalogRelation;
10598         SysScanDesc scan;
10599         ScanKeyData key[3];
10600         HeapTuple       depTuple;
10601
10602         catalogRelation = heap_open(DependRelationId, RowExclusiveLock);
10603
10604         ScanKeyInit(&key[0],
10605                                 Anum_pg_depend_classid,
10606                                 BTEqualStrategyNumber, F_OIDEQ,
10607                                 ObjectIdGetDatum(RelationRelationId));
10608         ScanKeyInit(&key[1],
10609                                 Anum_pg_depend_objid,
10610                                 BTEqualStrategyNumber, F_OIDEQ,
10611                                 ObjectIdGetDatum(relid));
10612         ScanKeyInit(&key[2],
10613                                 Anum_pg_depend_objsubid,
10614                                 BTEqualStrategyNumber, F_INT4EQ,
10615                                 Int32GetDatum(0));
10616
10617         scan = systable_beginscan(catalogRelation, DependDependerIndexId, true,
10618                                                           NULL, 3, key);
10619
10620         while (HeapTupleIsValid(depTuple = systable_getnext(scan)))
10621         {
10622                 Form_pg_depend dep = (Form_pg_depend) GETSTRUCT(depTuple);
10623
10624                 if (dep->refclassid == refclassid &&
10625                         dep->refobjid == refobjid &&
10626                         dep->refobjsubid == 0 &&
10627                         dep->deptype == DEPENDENCY_NORMAL)
10628                         simple_heap_delete(catalogRelation, &depTuple->t_self);
10629         }
10630
10631         systable_endscan(scan);
10632         heap_close(catalogRelation, RowExclusiveLock);
10633 }
10634
10635 /*
10636  * ALTER TABLE OF
10637  *
10638  * Attach a table to a composite type, as though it had been created with CREATE
10639  * TABLE OF.  All attname, atttypid, atttypmod and attcollation must match.  The
10640  * subject table must not have inheritance parents.  These restrictions ensure
10641  * that you cannot create a configuration impossible with CREATE TABLE OF alone.
10642  *
10643  * The address of the type is returned.
10644  */
10645 static ObjectAddress
10646 ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
10647 {
10648         Oid                     relid = RelationGetRelid(rel);
10649         Type            typetuple;
10650         Oid                     typeid;
10651         Relation        inheritsRelation,
10652                                 relationRelation;
10653         SysScanDesc scan;
10654         ScanKeyData key;
10655         AttrNumber      table_attno,
10656                                 type_attno;
10657         TupleDesc       typeTupleDesc,
10658                                 tableTupleDesc;
10659         ObjectAddress tableobj,
10660                                 typeobj;
10661         HeapTuple       classtuple;
10662
10663         /* Validate the type. */
10664         typetuple = typenameType(NULL, ofTypename, NULL);
10665         check_of_type(typetuple);
10666         typeid = HeapTupleGetOid(typetuple);
10667
10668         /* Fail if the table has any inheritance parents. */
10669         inheritsRelation = heap_open(InheritsRelationId, AccessShareLock);
10670         ScanKeyInit(&key,
10671                                 Anum_pg_inherits_inhrelid,
10672                                 BTEqualStrategyNumber, F_OIDEQ,
10673                                 ObjectIdGetDatum(relid));
10674         scan = systable_beginscan(inheritsRelation, InheritsRelidSeqnoIndexId,
10675                                                           true, NULL, 1, &key);
10676         if (HeapTupleIsValid(systable_getnext(scan)))
10677                 ereport(ERROR,
10678                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10679                                  errmsg("typed tables cannot inherit")));
10680         systable_endscan(scan);
10681         heap_close(inheritsRelation, AccessShareLock);
10682
10683         /*
10684          * Check the tuple descriptors for compatibility.  Unlike inheritance, we
10685          * require that the order also match.  However, attnotnull need not match.
10686          * Also unlike inheritance, we do not require matching relhasoids.
10687          */
10688         typeTupleDesc = lookup_rowtype_tupdesc(typeid, -1);
10689         tableTupleDesc = RelationGetDescr(rel);
10690         table_attno = 1;
10691         for (type_attno = 1; type_attno <= typeTupleDesc->natts; type_attno++)
10692         {
10693                 Form_pg_attribute type_attr,
10694                                         table_attr;
10695                 const char *type_attname,
10696                                    *table_attname;
10697
10698                 /* Get the next non-dropped type attribute. */
10699                 type_attr = typeTupleDesc->attrs[type_attno - 1];
10700                 if (type_attr->attisdropped)
10701                         continue;
10702                 type_attname = NameStr(type_attr->attname);
10703
10704                 /* Get the next non-dropped table attribute. */
10705                 do
10706                 {
10707                         if (table_attno > tableTupleDesc->natts)
10708                                 ereport(ERROR,
10709                                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
10710                                                  errmsg("table is missing column \"%s\"",
10711                                                                 type_attname)));
10712                         table_attr = tableTupleDesc->attrs[table_attno++ - 1];
10713                 } while (table_attr->attisdropped);
10714                 table_attname = NameStr(table_attr->attname);
10715
10716                 /* Compare name. */
10717                 if (strncmp(table_attname, type_attname, NAMEDATALEN) != 0)
10718                         ereport(ERROR,
10719                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
10720                                  errmsg("table has column \"%s\" where type requires \"%s\"",
10721                                                 table_attname, type_attname)));
10722
10723                 /* Compare type. */
10724                 if (table_attr->atttypid != type_attr->atttypid ||
10725                         table_attr->atttypmod != type_attr->atttypmod ||
10726                         table_attr->attcollation != type_attr->attcollation)
10727                         ereport(ERROR,
10728                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
10729                                   errmsg("table \"%s\" has different type for column \"%s\"",
10730                                                  RelationGetRelationName(rel), type_attname)));
10731         }
10732         DecrTupleDescRefCount(typeTupleDesc);
10733
10734         /* Any remaining columns at the end of the table had better be dropped. */
10735         for (; table_attno <= tableTupleDesc->natts; table_attno++)
10736         {
10737                 Form_pg_attribute table_attr = tableTupleDesc->attrs[table_attno - 1];
10738
10739                 if (!table_attr->attisdropped)
10740                         ereport(ERROR,
10741                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
10742                                          errmsg("table has extra column \"%s\"",
10743                                                         NameStr(table_attr->attname))));
10744         }
10745
10746         /* If the table was already typed, drop the existing dependency. */
10747         if (rel->rd_rel->reloftype)
10748                 drop_parent_dependency(relid, TypeRelationId, rel->rd_rel->reloftype);
10749
10750         /* Record a dependency on the new type. */
10751         tableobj.classId = RelationRelationId;
10752         tableobj.objectId = relid;
10753         tableobj.objectSubId = 0;
10754         typeobj.classId = TypeRelationId;
10755         typeobj.objectId = typeid;
10756         typeobj.objectSubId = 0;
10757         recordDependencyOn(&tableobj, &typeobj, DEPENDENCY_NORMAL);
10758
10759         /* Update pg_class.reloftype */
10760         relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
10761         classtuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
10762         if (!HeapTupleIsValid(classtuple))
10763                 elog(ERROR, "cache lookup failed for relation %u", relid);
10764         ((Form_pg_class) GETSTRUCT(classtuple))->reloftype = typeid;
10765         simple_heap_update(relationRelation, &classtuple->t_self, classtuple);
10766         CatalogUpdateIndexes(relationRelation, classtuple);
10767
10768         InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
10769
10770         heap_freetuple(classtuple);
10771         heap_close(relationRelation, RowExclusiveLock);
10772
10773         ReleaseSysCache(typetuple);
10774
10775         return typeobj;
10776 }
10777
10778 /*
10779  * ALTER TABLE NOT OF
10780  *
10781  * Detach a typed table from its originating type.  Just clear reloftype and
10782  * remove the dependency.
10783  */
10784 static void
10785 ATExecDropOf(Relation rel, LOCKMODE lockmode)
10786 {
10787         Oid                     relid = RelationGetRelid(rel);
10788         Relation        relationRelation;
10789         HeapTuple       tuple;
10790
10791         if (!OidIsValid(rel->rd_rel->reloftype))
10792                 ereport(ERROR,
10793                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10794                                  errmsg("\"%s\" is not a typed table",
10795                                                 RelationGetRelationName(rel))));
10796
10797         /*
10798          * We don't bother to check ownership of the type --- ownership of the
10799          * table is presumed enough rights.  No lock required on the type, either.
10800          */
10801
10802         drop_parent_dependency(relid, TypeRelationId, rel->rd_rel->reloftype);
10803
10804         /* Clear pg_class.reloftype */
10805         relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
10806         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
10807         if (!HeapTupleIsValid(tuple))
10808                 elog(ERROR, "cache lookup failed for relation %u", relid);
10809         ((Form_pg_class) GETSTRUCT(tuple))->reloftype = InvalidOid;
10810         simple_heap_update(relationRelation, &tuple->t_self, tuple);
10811         CatalogUpdateIndexes(relationRelation, tuple);
10812
10813         InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
10814
10815         heap_freetuple(tuple);
10816         heap_close(relationRelation, RowExclusiveLock);
10817 }
10818
10819 /*
10820  * relation_mark_replica_identity: Update a table's replica identity
10821  *
10822  * Iff ri_type = REPLICA_IDENTITY_INDEX, indexOid must be the Oid of a suitable
10823  * index. Otherwise, it should be InvalidOid.
10824  */
10825 static void
10826 relation_mark_replica_identity(Relation rel, char ri_type, Oid indexOid,
10827                                                            bool is_internal)
10828 {
10829         Relation        pg_index;
10830         Relation        pg_class;
10831         HeapTuple       pg_class_tuple;
10832         HeapTuple       pg_index_tuple;
10833         Form_pg_class pg_class_form;
10834         Form_pg_index pg_index_form;
10835
10836         ListCell   *index;
10837
10838         /*
10839          * Check whether relreplident has changed, and update it if so.
10840          */
10841         pg_class = heap_open(RelationRelationId, RowExclusiveLock);
10842         pg_class_tuple = SearchSysCacheCopy1(RELOID,
10843                                                                         ObjectIdGetDatum(RelationGetRelid(rel)));
10844         if (!HeapTupleIsValid(pg_class_tuple))
10845                 elog(ERROR, "cache lookup failed for relation \"%s\"",
10846                          RelationGetRelationName(rel));
10847         pg_class_form = (Form_pg_class) GETSTRUCT(pg_class_tuple);
10848         if (pg_class_form->relreplident != ri_type)
10849         {
10850                 pg_class_form->relreplident = ri_type;
10851                 simple_heap_update(pg_class, &pg_class_tuple->t_self, pg_class_tuple);
10852                 CatalogUpdateIndexes(pg_class, pg_class_tuple);
10853         }
10854         heap_close(pg_class, RowExclusiveLock);
10855         heap_freetuple(pg_class_tuple);
10856
10857         /*
10858          * Check whether the correct index is marked indisreplident; if so, we're
10859          * done.
10860          */
10861         if (OidIsValid(indexOid))
10862         {
10863                 Assert(ri_type == REPLICA_IDENTITY_INDEX);
10864
10865                 pg_index_tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexOid));
10866                 if (!HeapTupleIsValid(pg_index_tuple))
10867                         elog(ERROR, "cache lookup failed for index %u", indexOid);
10868                 pg_index_form = (Form_pg_index) GETSTRUCT(pg_index_tuple);
10869
10870                 if (pg_index_form->indisreplident)
10871                 {
10872                         ReleaseSysCache(pg_index_tuple);
10873                         return;
10874                 }
10875                 ReleaseSysCache(pg_index_tuple);
10876         }
10877
10878         /*
10879          * Clear the indisreplident flag from any index that had it previously,
10880          * and set it for any index that should have it now.
10881          */
10882         pg_index = heap_open(IndexRelationId, RowExclusiveLock);
10883         foreach(index, RelationGetIndexList(rel))
10884         {
10885                 Oid                     thisIndexOid = lfirst_oid(index);
10886                 bool            dirty = false;
10887
10888                 pg_index_tuple = SearchSysCacheCopy1(INDEXRELID,
10889                                                                                          ObjectIdGetDatum(thisIndexOid));
10890                 if (!HeapTupleIsValid(pg_index_tuple))
10891                         elog(ERROR, "cache lookup failed for index %u", thisIndexOid);
10892                 pg_index_form = (Form_pg_index) GETSTRUCT(pg_index_tuple);
10893
10894                 /*
10895                  * Unset the bit if set.  We know it's wrong because we checked this
10896                  * earlier.
10897                  */
10898                 if (pg_index_form->indisreplident)
10899                 {
10900                         dirty = true;
10901                         pg_index_form->indisreplident = false;
10902                 }
10903                 else if (thisIndexOid == indexOid)
10904                 {
10905                         dirty = true;
10906                         pg_index_form->indisreplident = true;
10907                 }
10908
10909                 if (dirty)
10910                 {
10911                         simple_heap_update(pg_index, &pg_index_tuple->t_self, pg_index_tuple);
10912                         CatalogUpdateIndexes(pg_index, pg_index_tuple);
10913                         InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
10914                                                                                  InvalidOid, is_internal);
10915                 }
10916                 heap_freetuple(pg_index_tuple);
10917         }
10918
10919         heap_close(pg_index, RowExclusiveLock);
10920 }
10921
10922 /*
10923  * ALTER TABLE <name> REPLICA IDENTITY ...
10924  */
10925 static void
10926 ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode)
10927 {
10928         Oid                     indexOid;
10929         Relation        indexRel;
10930         int                     key;
10931
10932         if (stmt->identity_type == REPLICA_IDENTITY_DEFAULT)
10933         {
10934                 relation_mark_replica_identity(rel, stmt->identity_type, InvalidOid, true);
10935                 return;
10936         }
10937         else if (stmt->identity_type == REPLICA_IDENTITY_FULL)
10938         {
10939                 relation_mark_replica_identity(rel, stmt->identity_type, InvalidOid, true);
10940                 return;
10941         }
10942         else if (stmt->identity_type == REPLICA_IDENTITY_NOTHING)
10943         {
10944                 relation_mark_replica_identity(rel, stmt->identity_type, InvalidOid, true);
10945                 return;
10946         }
10947         else if (stmt->identity_type == REPLICA_IDENTITY_INDEX)
10948         {
10949                  /* fallthrough */ ;
10950         }
10951         else
10952                 elog(ERROR, "unexpected identity type %u", stmt->identity_type);
10953
10954
10955         /* Check that the index exists */
10956         indexOid = get_relname_relid(stmt->name, rel->rd_rel->relnamespace);
10957         if (!OidIsValid(indexOid))
10958                 ereport(ERROR,
10959                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
10960                                  errmsg("index \"%s\" for table \"%s\" does not exist",
10961                                                 stmt->name, RelationGetRelationName(rel))));
10962
10963         indexRel = index_open(indexOid, ShareLock);
10964
10965         /* Check that the index is on the relation we're altering. */
10966         if (indexRel->rd_index == NULL ||
10967                 indexRel->rd_index->indrelid != RelationGetRelid(rel))
10968                 ereport(ERROR,
10969                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10970                                  errmsg("\"%s\" is not an index for table \"%s\"",
10971                                                 RelationGetRelationName(indexRel),
10972                                                 RelationGetRelationName(rel))));
10973         /* The AM must support uniqueness, and the index must in fact be unique. */
10974         if (!indexRel->rd_am->amcanunique || !indexRel->rd_index->indisunique)
10975                 ereport(ERROR,
10976                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10977                          errmsg("cannot use non-unique index \"%s\" as replica identity",
10978                                         RelationGetRelationName(indexRel))));
10979         /* Deferred indexes are not guaranteed to be always unique. */
10980         if (!indexRel->rd_index->indimmediate)
10981                 ereport(ERROR,
10982                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
10983                   errmsg("cannot use non-immediate index \"%s\" as replica identity",
10984                                  RelationGetRelationName(indexRel))));
10985         /* Expression indexes aren't supported. */
10986         if (RelationGetIndexExpressions(indexRel) != NIL)
10987                 ereport(ERROR,
10988                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
10989                          errmsg("cannot use expression index \"%s\" as replica identity",
10990                                         RelationGetRelationName(indexRel))));
10991         /* Predicate indexes aren't supported. */
10992         if (RelationGetIndexPredicate(indexRel) != NIL)
10993                 ereport(ERROR,
10994                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
10995                                  errmsg("cannot use partial index \"%s\" as replica identity",
10996                                                 RelationGetRelationName(indexRel))));
10997         /* And neither are invalid indexes. */
10998         if (!IndexIsValid(indexRel->rd_index))
10999                 ereport(ERROR,
11000                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11001                                  errmsg("cannot use invalid index \"%s\" as replica identity",
11002                                                 RelationGetRelationName(indexRel))));
11003
11004         /* Check index for nullable columns. */
11005         for (key = 0; key < indexRel->rd_index->indnatts; key++)
11006         {
11007                 int16           attno = indexRel->rd_index->indkey.values[key];
11008                 Form_pg_attribute attr;
11009
11010                 /* Of the system columns, only oid is indexable. */
11011                 if (attno <= 0 && attno != ObjectIdAttributeNumber)
11012                         elog(ERROR, "internal column %u in unique index \"%s\"",
11013                                  attno, RelationGetRelationName(indexRel));
11014
11015                 attr = rel->rd_att->attrs[attno - 1];
11016                 if (!attr->attnotnull)
11017                         ereport(ERROR,
11018                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11019                                          errmsg("index \"%s\" cannot be used as replica identity because column \"%s\" is nullable",
11020                                                         RelationGetRelationName(indexRel),
11021                                                         NameStr(attr->attname))));
11022         }
11023
11024         /* This index is suitable for use as a replica identity. Mark it. */
11025         relation_mark_replica_identity(rel, stmt->identity_type, indexOid, true);
11026
11027         index_close(indexRel, NoLock);
11028 }
11029
11030 /*
11031  * ALTER TABLE ENABLE/DISABLE ROW LEVEL SECURITY
11032  */
11033 static void
11034 ATExecEnableRowSecurity(Relation rel)
11035 {
11036         Relation        pg_class;
11037         Oid                     relid;
11038         HeapTuple       tuple;
11039
11040         relid = RelationGetRelid(rel);
11041
11042         pg_class = heap_open(RelationRelationId, RowExclusiveLock);
11043
11044         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
11045
11046         if (!HeapTupleIsValid(tuple))
11047                 elog(ERROR, "cache lookup failed for relation %u", relid);
11048
11049         ((Form_pg_class) GETSTRUCT(tuple))->relrowsecurity = true;
11050         simple_heap_update(pg_class, &tuple->t_self, tuple);
11051
11052         /* keep catalog indexes current */
11053         CatalogUpdateIndexes(pg_class, tuple);
11054
11055         heap_close(pg_class, RowExclusiveLock);
11056         heap_freetuple(tuple);
11057 }
11058
11059 static void
11060 ATExecDisableRowSecurity(Relation rel)
11061 {
11062         Relation        pg_class;
11063         Oid                     relid;
11064         HeapTuple       tuple;
11065
11066         relid = RelationGetRelid(rel);
11067
11068         /* Pull the record for this relation and update it */
11069         pg_class = heap_open(RelationRelationId, RowExclusiveLock);
11070
11071         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
11072
11073         if (!HeapTupleIsValid(tuple))
11074                 elog(ERROR, "cache lookup failed for relation %u", relid);
11075
11076         ((Form_pg_class) GETSTRUCT(tuple))->relrowsecurity = false;
11077         simple_heap_update(pg_class, &tuple->t_self, tuple);
11078
11079         /* keep catalog indexes current */
11080         CatalogUpdateIndexes(pg_class, tuple);
11081
11082         heap_close(pg_class, RowExclusiveLock);
11083         heap_freetuple(tuple);
11084 }
11085
11086 /*
11087  * ALTER TABLE FORCE/NO FORCE ROW LEVEL SECURITY
11088  */
11089 static void
11090 ATExecForceNoForceRowSecurity(Relation rel, bool force_rls)
11091 {
11092         Relation        pg_class;
11093         Oid                     relid;
11094         HeapTuple       tuple;
11095
11096         relid = RelationGetRelid(rel);
11097
11098         pg_class = heap_open(RelationRelationId, RowExclusiveLock);
11099
11100         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
11101
11102         if (!HeapTupleIsValid(tuple))
11103                 elog(ERROR, "cache lookup failed for relation %u", relid);
11104
11105         ((Form_pg_class) GETSTRUCT(tuple))->relforcerowsecurity = force_rls;
11106         simple_heap_update(pg_class, &tuple->t_self, tuple);
11107
11108         /* keep catalog indexes current */
11109         CatalogUpdateIndexes(pg_class, tuple);
11110
11111         heap_close(pg_class, RowExclusiveLock);
11112         heap_freetuple(tuple);
11113 }
11114
11115 /*
11116  * ALTER FOREIGN TABLE <name> OPTIONS (...)
11117  */
11118 static void
11119 ATExecGenericOptions(Relation rel, List *options)
11120 {
11121         Relation        ftrel;
11122         ForeignServer *server;
11123         ForeignDataWrapper *fdw;
11124         HeapTuple       tuple;
11125         bool            isnull;
11126         Datum           repl_val[Natts_pg_foreign_table];
11127         bool            repl_null[Natts_pg_foreign_table];
11128         bool            repl_repl[Natts_pg_foreign_table];
11129         Datum           datum;
11130         Form_pg_foreign_table tableform;
11131
11132         if (options == NIL)
11133                 return;
11134
11135         ftrel = heap_open(ForeignTableRelationId, RowExclusiveLock);
11136
11137         tuple = SearchSysCacheCopy1(FOREIGNTABLEREL, rel->rd_id);
11138         if (!HeapTupleIsValid(tuple))
11139                 ereport(ERROR,
11140                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
11141                                  errmsg("foreign table \"%s\" does not exist",
11142                                                 RelationGetRelationName(rel))));
11143         tableform = (Form_pg_foreign_table) GETSTRUCT(tuple);
11144         server = GetForeignServer(tableform->ftserver);
11145         fdw = GetForeignDataWrapper(server->fdwid);
11146
11147         memset(repl_val, 0, sizeof(repl_val));
11148         memset(repl_null, false, sizeof(repl_null));
11149         memset(repl_repl, false, sizeof(repl_repl));
11150
11151         /* Extract the current options */
11152         datum = SysCacheGetAttr(FOREIGNTABLEREL,
11153                                                         tuple,
11154                                                         Anum_pg_foreign_table_ftoptions,
11155                                                         &isnull);
11156         if (isnull)
11157                 datum = PointerGetDatum(NULL);
11158
11159         /* Transform the options */
11160         datum = transformGenericOptions(ForeignTableRelationId,
11161                                                                         datum,
11162                                                                         options,
11163                                                                         fdw->fdwvalidator);
11164
11165         if (PointerIsValid(DatumGetPointer(datum)))
11166                 repl_val[Anum_pg_foreign_table_ftoptions - 1] = datum;
11167         else
11168                 repl_null[Anum_pg_foreign_table_ftoptions - 1] = true;
11169
11170         repl_repl[Anum_pg_foreign_table_ftoptions - 1] = true;
11171
11172         /* Everything looks good - update the tuple */
11173
11174         tuple = heap_modify_tuple(tuple, RelationGetDescr(ftrel),
11175                                                           repl_val, repl_null, repl_repl);
11176
11177         simple_heap_update(ftrel, &tuple->t_self, tuple);
11178         CatalogUpdateIndexes(ftrel, tuple);
11179
11180         InvokeObjectPostAlterHook(ForeignTableRelationId,
11181                                                           RelationGetRelid(rel), 0);
11182
11183         heap_close(ftrel, RowExclusiveLock);
11184
11185         heap_freetuple(tuple);
11186 }
11187
11188 /*
11189  * Preparation phase for SET LOGGED/UNLOGGED
11190  *
11191  * This verifies that we're not trying to change a temp table.  Also,
11192  * existing foreign key constraints are checked to avoid ending up with
11193  * permanent tables referencing unlogged tables.
11194  *
11195  * Return value is false if the operation is a no-op (in which case the
11196  * checks are skipped), otherwise true.
11197  */
11198 static bool
11199 ATPrepChangePersistence(Relation rel, bool toLogged)
11200 {
11201         Relation        pg_constraint;
11202         HeapTuple       tuple;
11203         SysScanDesc scan;
11204         ScanKeyData skey[1];
11205
11206         /*
11207          * Disallow changing status for a temp table.  Also verify whether we can
11208          * get away with doing nothing; in such cases we don't need to run the
11209          * checks below, either.
11210          */
11211         switch (rel->rd_rel->relpersistence)
11212         {
11213                 case RELPERSISTENCE_TEMP:
11214                         ereport(ERROR,
11215                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
11216                                          errmsg("cannot change logged status of table %s",
11217                                                         RelationGetRelationName(rel)),
11218                                          errdetail("Table %s is temporary.",
11219                                                            RelationGetRelationName(rel)),
11220                                          errtable(rel)));
11221                         break;
11222                 case RELPERSISTENCE_PERMANENT:
11223                         if (toLogged)
11224                                 /* nothing to do */
11225                                 return false;
11226                         break;
11227                 case RELPERSISTENCE_UNLOGGED:
11228                         if (!toLogged)
11229                                 /* nothing to do */
11230                                 return false;
11231                         break;
11232         }
11233
11234         /*
11235          * Check existing foreign key constraints to preserve the invariant that
11236          * permanent tables cannot reference unlogged ones.  Self-referencing
11237          * foreign keys can safely be ignored.
11238          */
11239         pg_constraint = heap_open(ConstraintRelationId, AccessShareLock);
11240
11241         /*
11242          * Scan conrelid if changing to permanent, else confrelid.  This also
11243          * determines whether a useful index exists.
11244          */
11245         ScanKeyInit(&skey[0],
11246                                 toLogged ? Anum_pg_constraint_conrelid :
11247                                 Anum_pg_constraint_confrelid,
11248                                 BTEqualStrategyNumber, F_OIDEQ,
11249                                 ObjectIdGetDatum(RelationGetRelid(rel)));
11250         scan = systable_beginscan(pg_constraint,
11251                                                           toLogged ? ConstraintRelidIndexId : InvalidOid,
11252                                                           true, NULL, 1, skey);
11253
11254         while (HeapTupleIsValid(tuple = systable_getnext(scan)))
11255         {
11256                 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
11257
11258                 if (con->contype == CONSTRAINT_FOREIGN)
11259                 {
11260                         Oid                     foreignrelid;
11261                         Relation        foreignrel;
11262
11263                         /* the opposite end of what we used as scankey */
11264                         foreignrelid = toLogged ? con->confrelid : con->conrelid;
11265
11266                         /* ignore if self-referencing */
11267                         if (RelationGetRelid(rel) == foreignrelid)
11268                                 continue;
11269
11270                         foreignrel = relation_open(foreignrelid, AccessShareLock);
11271
11272                         if (toLogged)
11273                         {
11274                                 if (foreignrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT)
11275                                         ereport(ERROR,
11276                                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
11277                                                  errmsg("cannot change status of table %s to logged",
11278                                                                 RelationGetRelationName(rel)),
11279                                                   errdetail("Table %s references unlogged table %s.",
11280                                                                         RelationGetRelationName(rel),
11281                                                                         RelationGetRelationName(foreignrel)),
11282                                                          errtableconstraint(rel, NameStr(con->conname))));
11283                         }
11284                         else
11285                         {
11286                                 if (foreignrel->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT)
11287                                         ereport(ERROR,
11288                                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
11289                                            errmsg("cannot change status of table %s to unlogged",
11290                                                           RelationGetRelationName(rel)),
11291                                           errdetail("Logged table %s is referenced by table %s.",
11292                                                                 RelationGetRelationName(foreignrel),
11293                                                                 RelationGetRelationName(rel)),
11294                                                          errtableconstraint(rel, NameStr(con->conname))));
11295                         }
11296
11297                         relation_close(foreignrel, AccessShareLock);
11298                 }
11299         }
11300
11301         systable_endscan(scan);
11302
11303         heap_close(pg_constraint, AccessShareLock);
11304
11305         return true;
11306 }
11307
11308 /*
11309  * Execute ALTER TABLE SET SCHEMA
11310  */
11311 ObjectAddress
11312 AlterTableNamespace(AlterObjectSchemaStmt *stmt, Oid *oldschema)
11313 {
11314         Relation        rel;
11315         Oid                     relid;
11316         Oid                     oldNspOid;
11317         Oid                     nspOid;
11318         RangeVar   *newrv;
11319         ObjectAddresses *objsMoved;
11320         ObjectAddress myself;
11321
11322         relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
11323                                                                          stmt->missing_ok, false,
11324                                                                          RangeVarCallbackForAlterRelation,
11325                                                                          (void *) stmt);
11326
11327         if (!OidIsValid(relid))
11328         {
11329                 ereport(NOTICE,
11330                                 (errmsg("relation \"%s\" does not exist, skipping",
11331                                                 stmt->relation->relname)));
11332                 return InvalidObjectAddress;
11333         }
11334
11335         rel = relation_open(relid, NoLock);
11336
11337         oldNspOid = RelationGetNamespace(rel);
11338
11339         /* If it's an owned sequence, disallow moving it by itself. */
11340         if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
11341         {
11342                 Oid                     tableId;
11343                 int32           colId;
11344
11345                 if (sequenceIsOwned(relid, &tableId, &colId))
11346                         ereport(ERROR,
11347                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11348                                  errmsg("cannot move an owned sequence into another schema"),
11349                                          errdetail("Sequence \"%s\" is linked to table \"%s\".",
11350                                                            RelationGetRelationName(rel),
11351                                                            get_rel_name(tableId))));
11352         }
11353
11354         /* Get and lock schema OID and check its permissions. */
11355         newrv = makeRangeVar(stmt->newschema, RelationGetRelationName(rel), -1);
11356         nspOid = RangeVarGetAndCheckCreationNamespace(newrv, NoLock, NULL);
11357
11358         /* common checks on switching namespaces */
11359         CheckSetNamespace(oldNspOid, nspOid, RelationRelationId, relid);
11360
11361         objsMoved = new_object_addresses();
11362         AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
11363         free_object_addresses(objsMoved);
11364
11365         ObjectAddressSet(myself, RelationRelationId, relid);
11366
11367         if (oldschema)
11368                 *oldschema = oldNspOid;
11369
11370         /* close rel, but keep lock until commit */
11371         relation_close(rel, NoLock);
11372
11373         return myself;
11374 }
11375
11376 /*
11377  * The guts of relocating a table or materialized view to another namespace:
11378  * besides moving the relation itself, its dependent objects are relocated to
11379  * the new schema.
11380  */
11381 void
11382 AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid,
11383                                                         ObjectAddresses *objsMoved)
11384 {
11385         Relation        classRel;
11386
11387         Assert(objsMoved != NULL);
11388
11389         /* OK, modify the pg_class row and pg_depend entry */
11390         classRel = heap_open(RelationRelationId, RowExclusiveLock);
11391
11392         AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid,
11393                                                                    nspOid, true, objsMoved);
11394
11395         /* Fix the table's row type too */
11396         AlterTypeNamespaceInternal(rel->rd_rel->reltype,
11397                                                            nspOid, false, false, objsMoved);
11398
11399         /* Fix other dependent stuff */
11400         if (rel->rd_rel->relkind == RELKIND_RELATION ||
11401                 rel->rd_rel->relkind == RELKIND_MATVIEW)
11402         {
11403                 AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
11404                 AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
11405                                                    objsMoved, AccessExclusiveLock);
11406                 AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
11407                                                                   false, objsMoved);
11408         }
11409
11410         heap_close(classRel, RowExclusiveLock);
11411 }
11412
11413 /*
11414  * The guts of relocating a relation to another namespace: fix the pg_class
11415  * entry, and the pg_depend entry if any.  Caller must already have
11416  * opened and write-locked pg_class.
11417  */
11418 void
11419 AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
11420                                                            Oid oldNspOid, Oid newNspOid,
11421                                                            bool hasDependEntry,
11422                                                            ObjectAddresses *objsMoved)
11423 {
11424         HeapTuple       classTup;
11425         Form_pg_class classForm;
11426         ObjectAddress thisobj;
11427
11428         classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid));
11429         if (!HeapTupleIsValid(classTup))
11430                 elog(ERROR, "cache lookup failed for relation %u", relOid);
11431         classForm = (Form_pg_class) GETSTRUCT(classTup);
11432
11433         Assert(classForm->relnamespace == oldNspOid);
11434
11435         thisobj.classId = RelationRelationId;
11436         thisobj.objectId = relOid;
11437         thisobj.objectSubId = 0;
11438
11439         /*
11440          * Do nothing when there's nothing to do.
11441          */
11442         if (!object_address_present(&thisobj, objsMoved))
11443         {
11444                 /* check for duplicate name (more friendly than unique-index failure) */
11445                 if (get_relname_relid(NameStr(classForm->relname),
11446                                                           newNspOid) != InvalidOid)
11447                         ereport(ERROR,
11448                                         (errcode(ERRCODE_DUPLICATE_TABLE),
11449                                          errmsg("relation \"%s\" already exists in schema \"%s\"",
11450                                                         NameStr(classForm->relname),
11451                                                         get_namespace_name(newNspOid))));
11452
11453                 /* classTup is a copy, so OK to scribble on */
11454                 classForm->relnamespace = newNspOid;
11455
11456                 simple_heap_update(classRel, &classTup->t_self, classTup);
11457                 CatalogUpdateIndexes(classRel, classTup);
11458
11459                 /* Update dependency on schema if caller said so */
11460                 if (hasDependEntry &&
11461                         changeDependencyFor(RelationRelationId,
11462                                                                 relOid,
11463                                                                 NamespaceRelationId,
11464                                                                 oldNspOid,
11465                                                                 newNspOid) != 1)
11466                         elog(ERROR, "failed to change schema dependency for relation \"%s\"",
11467                                  NameStr(classForm->relname));
11468
11469                 add_exact_object_address(&thisobj, objsMoved);
11470
11471                 InvokeObjectPostAlterHook(RelationRelationId, relOid, 0);
11472         }
11473
11474         heap_freetuple(classTup);
11475 }
11476
11477 /*
11478  * Move all indexes for the specified relation to another namespace.
11479  *
11480  * Note: we assume adequate permission checking was done by the caller,
11481  * and that the caller has a suitable lock on the owning relation.
11482  */
11483 static void
11484 AlterIndexNamespaces(Relation classRel, Relation rel,
11485                                          Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved)
11486 {
11487         List       *indexList;
11488         ListCell   *l;
11489
11490         indexList = RelationGetIndexList(rel);
11491
11492         foreach(l, indexList)
11493         {
11494                 Oid                     indexOid = lfirst_oid(l);
11495                 ObjectAddress thisobj;
11496
11497                 thisobj.classId = RelationRelationId;
11498                 thisobj.objectId = indexOid;
11499                 thisobj.objectSubId = 0;
11500
11501                 /*
11502                  * Note: currently, the index will not have its own dependency on the
11503                  * namespace, so we don't need to do changeDependencyFor(). There's no
11504                  * row type in pg_type, either.
11505                  *
11506                  * XXX this objsMoved test may be pointless -- surely we have a single
11507                  * dependency link from a relation to each index?
11508                  */
11509                 if (!object_address_present(&thisobj, objsMoved))
11510                 {
11511                         AlterRelationNamespaceInternal(classRel, indexOid,
11512                                                                                    oldNspOid, newNspOid,
11513                                                                                    false, objsMoved);
11514                         add_exact_object_address(&thisobj, objsMoved);
11515                 }
11516         }
11517
11518         list_free(indexList);
11519 }
11520
11521 /*
11522  * Move all SERIAL-column sequences of the specified relation to another
11523  * namespace.
11524  *
11525  * Note: we assume adequate permission checking was done by the caller,
11526  * and that the caller has a suitable lock on the owning relation.
11527  */
11528 static void
11529 AlterSeqNamespaces(Relation classRel, Relation rel,
11530                                    Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved,
11531                                    LOCKMODE lockmode)
11532 {
11533         Relation        depRel;
11534         SysScanDesc scan;
11535         ScanKeyData key[2];
11536         HeapTuple       tup;
11537
11538         /*
11539          * SERIAL sequences are those having an auto dependency on one of the
11540          * table's columns (we don't care *which* column, exactly).
11541          */
11542         depRel = heap_open(DependRelationId, AccessShareLock);
11543
11544         ScanKeyInit(&key[0],
11545                                 Anum_pg_depend_refclassid,
11546                                 BTEqualStrategyNumber, F_OIDEQ,
11547                                 ObjectIdGetDatum(RelationRelationId));
11548         ScanKeyInit(&key[1],
11549                                 Anum_pg_depend_refobjid,
11550                                 BTEqualStrategyNumber, F_OIDEQ,
11551                                 ObjectIdGetDatum(RelationGetRelid(rel)));
11552         /* we leave refobjsubid unspecified */
11553
11554         scan = systable_beginscan(depRel, DependReferenceIndexId, true,
11555                                                           NULL, 2, key);
11556
11557         while (HeapTupleIsValid(tup = systable_getnext(scan)))
11558         {
11559                 Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
11560                 Relation        seqRel;
11561
11562                 /* skip dependencies other than auto dependencies on columns */
11563                 if (depForm->refobjsubid == 0 ||
11564                         depForm->classid != RelationRelationId ||
11565                         depForm->objsubid != 0 ||
11566                         depForm->deptype != DEPENDENCY_AUTO)
11567                         continue;
11568
11569                 /* Use relation_open just in case it's an index */
11570                 seqRel = relation_open(depForm->objid, lockmode);
11571
11572                 /* skip non-sequence relations */
11573                 if (RelationGetForm(seqRel)->relkind != RELKIND_SEQUENCE)
11574                 {
11575                         /* No need to keep the lock */
11576                         relation_close(seqRel, lockmode);
11577                         continue;
11578                 }
11579
11580                 /* Fix the pg_class and pg_depend entries */
11581                 AlterRelationNamespaceInternal(classRel, depForm->objid,
11582                                                                            oldNspOid, newNspOid,
11583                                                                            true, objsMoved);
11584
11585                 /*
11586                  * Sequences have entries in pg_type. We need to be careful to move
11587                  * them to the new namespace, too.
11588                  */
11589                 AlterTypeNamespaceInternal(RelationGetForm(seqRel)->reltype,
11590                                                                    newNspOid, false, false, objsMoved);
11591
11592                 /* Now we can close it.  Keep the lock till end of transaction. */
11593                 relation_close(seqRel, NoLock);
11594         }
11595
11596         systable_endscan(scan);
11597
11598         relation_close(depRel, AccessShareLock);
11599 }
11600
11601
11602 /*
11603  * This code supports
11604  *      CREATE TEMP TABLE ... ON COMMIT { DROP | PRESERVE ROWS | DELETE ROWS }
11605  *
11606  * Because we only support this for TEMP tables, it's sufficient to remember
11607  * the state in a backend-local data structure.
11608  */
11609
11610 /*
11611  * Register a newly-created relation's ON COMMIT action.
11612  */
11613 void
11614 register_on_commit_action(Oid relid, OnCommitAction action)
11615 {
11616         OnCommitItem *oc;
11617         MemoryContext oldcxt;
11618
11619         /*
11620          * We needn't bother registering the relation unless there is an ON COMMIT
11621          * action we need to take.
11622          */
11623         if (action == ONCOMMIT_NOOP || action == ONCOMMIT_PRESERVE_ROWS)
11624                 return;
11625
11626         oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
11627
11628         oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
11629         oc->relid = relid;
11630         oc->oncommit = action;
11631         oc->creating_subid = GetCurrentSubTransactionId();
11632         oc->deleting_subid = InvalidSubTransactionId;
11633
11634         on_commits = lcons(oc, on_commits);
11635
11636         MemoryContextSwitchTo(oldcxt);
11637 }
11638
11639 /*
11640  * Unregister any ON COMMIT action when a relation is deleted.
11641  *
11642  * Actually, we only mark the OnCommitItem entry as to be deleted after commit.
11643  */
11644 void
11645 remove_on_commit_action(Oid relid)
11646 {
11647         ListCell   *l;
11648
11649         foreach(l, on_commits)
11650         {
11651                 OnCommitItem *oc = (OnCommitItem *) lfirst(l);
11652
11653                 if (oc->relid == relid)
11654                 {
11655                         oc->deleting_subid = GetCurrentSubTransactionId();
11656                         break;
11657                 }
11658         }
11659 }
11660
11661 /*
11662  * Perform ON COMMIT actions.
11663  *
11664  * This is invoked just before actually committing, since it's possible
11665  * to encounter errors.
11666  */
11667 void
11668 PreCommit_on_commit_actions(void)
11669 {
11670         ListCell   *l;
11671         List       *oids_to_truncate = NIL;
11672
11673         foreach(l, on_commits)
11674         {
11675                 OnCommitItem *oc = (OnCommitItem *) lfirst(l);
11676
11677                 /* Ignore entry if already dropped in this xact */
11678                 if (oc->deleting_subid != InvalidSubTransactionId)
11679                         continue;
11680
11681                 switch (oc->oncommit)
11682                 {
11683                         case ONCOMMIT_NOOP:
11684                         case ONCOMMIT_PRESERVE_ROWS:
11685                                 /* Do nothing (there shouldn't be such entries, actually) */
11686                                 break;
11687                         case ONCOMMIT_DELETE_ROWS:
11688
11689                                 /*
11690                                  * If this transaction hasn't accessed any temporary
11691                                  * relations, we can skip truncating ON COMMIT DELETE ROWS
11692                                  * tables, as they must still be empty.
11693                                  */
11694                                 if (MyXactAccessedTempRel)
11695                                         oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
11696                                 break;
11697                         case ONCOMMIT_DROP:
11698                                 {
11699                                         ObjectAddress object;
11700
11701                                         object.classId = RelationRelationId;
11702                                         object.objectId = oc->relid;
11703                                         object.objectSubId = 0;
11704
11705                                         /*
11706                                          * Since this is an automatic drop, rather than one
11707                                          * directly initiated by the user, we pass the
11708                                          * PERFORM_DELETION_INTERNAL flag.
11709                                          */
11710                                         performDeletion(&object,
11711                                                                         DROP_CASCADE, PERFORM_DELETION_INTERNAL);
11712
11713                                         /*
11714                                          * Note that table deletion will call
11715                                          * remove_on_commit_action, so the entry should get marked
11716                                          * as deleted.
11717                                          */
11718                                         Assert(oc->deleting_subid != InvalidSubTransactionId);
11719                                         break;
11720                                 }
11721                 }
11722         }
11723         if (oids_to_truncate != NIL)
11724         {
11725                 heap_truncate(oids_to_truncate);
11726                 CommandCounterIncrement();              /* XXX needed? */
11727         }
11728 }
11729
11730 /*
11731  * Post-commit or post-abort cleanup for ON COMMIT management.
11732  *
11733  * All we do here is remove no-longer-needed OnCommitItem entries.
11734  *
11735  * During commit, remove entries that were deleted during this transaction;
11736  * during abort, remove those created during this transaction.
11737  */
11738 void
11739 AtEOXact_on_commit_actions(bool isCommit)
11740 {
11741         ListCell   *cur_item;
11742         ListCell   *prev_item;
11743
11744         prev_item = NULL;
11745         cur_item = list_head(on_commits);
11746
11747         while (cur_item != NULL)
11748         {
11749                 OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
11750
11751                 if (isCommit ? oc->deleting_subid != InvalidSubTransactionId :
11752                         oc->creating_subid != InvalidSubTransactionId)
11753                 {
11754                         /* cur_item must be removed */
11755                         on_commits = list_delete_cell(on_commits, cur_item, prev_item);
11756                         pfree(oc);
11757                         if (prev_item)
11758                                 cur_item = lnext(prev_item);
11759                         else
11760                                 cur_item = list_head(on_commits);
11761                 }
11762                 else
11763                 {
11764                         /* cur_item must be preserved */
11765                         oc->creating_subid = InvalidSubTransactionId;
11766                         oc->deleting_subid = InvalidSubTransactionId;
11767                         prev_item = cur_item;
11768                         cur_item = lnext(prev_item);
11769                 }
11770         }
11771 }
11772
11773 /*
11774  * Post-subcommit or post-subabort cleanup for ON COMMIT management.
11775  *
11776  * During subabort, we can immediately remove entries created during this
11777  * subtransaction.  During subcommit, just relabel entries marked during
11778  * this subtransaction as being the parent's responsibility.
11779  */
11780 void
11781 AtEOSubXact_on_commit_actions(bool isCommit, SubTransactionId mySubid,
11782                                                           SubTransactionId parentSubid)
11783 {
11784         ListCell   *cur_item;
11785         ListCell   *prev_item;
11786
11787         prev_item = NULL;
11788         cur_item = list_head(on_commits);
11789
11790         while (cur_item != NULL)
11791         {
11792                 OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
11793
11794                 if (!isCommit && oc->creating_subid == mySubid)
11795                 {
11796                         /* cur_item must be removed */
11797                         on_commits = list_delete_cell(on_commits, cur_item, prev_item);
11798                         pfree(oc);
11799                         if (prev_item)
11800                                 cur_item = lnext(prev_item);
11801                         else
11802                                 cur_item = list_head(on_commits);
11803                 }
11804                 else
11805                 {
11806                         /* cur_item must be preserved */
11807                         if (oc->creating_subid == mySubid)
11808                                 oc->creating_subid = parentSubid;
11809                         if (oc->deleting_subid == mySubid)
11810                                 oc->deleting_subid = isCommit ? parentSubid : InvalidSubTransactionId;
11811                         prev_item = cur_item;
11812                         cur_item = lnext(prev_item);
11813                 }
11814         }
11815 }
11816
11817 /*
11818  * This is intended as a callback for RangeVarGetRelidExtended().  It allows
11819  * the relation to be locked only if (1) it's a plain table, materialized
11820  * view, or TOAST table and (2) the current user is the owner (or the
11821  * superuser).  This meets the permission-checking needs of CLUSTER, REINDEX
11822  * TABLE, and REFRESH MATERIALIZED VIEW; we expose it here so that it can be
11823  * used by all.
11824  */
11825 void
11826 RangeVarCallbackOwnsTable(const RangeVar *relation,
11827                                                   Oid relId, Oid oldRelId, void *arg)
11828 {
11829         char            relkind;
11830
11831         /* Nothing to do if the relation was not found. */
11832         if (!OidIsValid(relId))
11833                 return;
11834
11835         /*
11836          * If the relation does exist, check whether it's an index.  But note that
11837          * the relation might have been dropped between the time we did the name
11838          * lookup and now.  In that case, there's nothing to do.
11839          */
11840         relkind = get_rel_relkind(relId);
11841         if (!relkind)
11842                 return;
11843         if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
11844                 relkind != RELKIND_MATVIEW)
11845                 ereport(ERROR,
11846                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11847                                  errmsg("\"%s\" is not a table or materialized view", relation->relname)));
11848
11849         /* Check permissions */
11850         if (!pg_class_ownercheck(relId, GetUserId()))
11851                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, relation->relname);
11852 }
11853
11854 /*
11855  * Callback to RangeVarGetRelidExtended(), similar to
11856  * RangeVarCallbackOwnsTable() but without checks on the type of the relation.
11857  */
11858 void
11859 RangeVarCallbackOwnsRelation(const RangeVar *relation,
11860                                                          Oid relId, Oid oldRelId, void *arg)
11861 {
11862         HeapTuple       tuple;
11863
11864         /* Nothing to do if the relation was not found. */
11865         if (!OidIsValid(relId))
11866                 return;
11867
11868         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relId));
11869         if (!HeapTupleIsValid(tuple))           /* should not happen */
11870                 elog(ERROR, "cache lookup failed for relation %u", relId);
11871
11872         if (!pg_class_ownercheck(relId, GetUserId()))
11873                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
11874                                            relation->relname);
11875
11876         if (!allowSystemTableMods &&
11877                 IsSystemClass(relId, (Form_pg_class) GETSTRUCT(tuple)))
11878                 ereport(ERROR,
11879                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
11880                                  errmsg("permission denied: \"%s\" is a system catalog",
11881                                                 relation->relname)));
11882
11883         ReleaseSysCache(tuple);
11884 }
11885
11886 /*
11887  * Common RangeVarGetRelid callback for rename, set schema, and alter table
11888  * processing.
11889  */
11890 static void
11891 RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
11892                                                                  void *arg)
11893 {
11894         Node       *stmt = (Node *) arg;
11895         ObjectType      reltype;
11896         HeapTuple       tuple;
11897         Form_pg_class classform;
11898         AclResult       aclresult;
11899         char            relkind;
11900
11901         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
11902         if (!HeapTupleIsValid(tuple))
11903                 return;                                 /* concurrently dropped */
11904         classform = (Form_pg_class) GETSTRUCT(tuple);
11905         relkind = classform->relkind;
11906
11907         /* Must own relation. */
11908         if (!pg_class_ownercheck(relid, GetUserId()))
11909                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, rv->relname);
11910
11911         /* No system table modifications unless explicitly allowed. */
11912         if (!allowSystemTableMods && IsSystemClass(relid, classform))
11913                 ereport(ERROR,
11914                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
11915                                  errmsg("permission denied: \"%s\" is a system catalog",
11916                                                 rv->relname)));
11917
11918         /*
11919          * Extract the specified relation type from the statement parse tree.
11920          *
11921          * Also, for ALTER .. RENAME, check permissions: the user must (still)
11922          * have CREATE rights on the containing namespace.
11923          */
11924         if (IsA(stmt, RenameStmt))
11925         {
11926                 aclresult = pg_namespace_aclcheck(classform->relnamespace,
11927                                                                                   GetUserId(), ACL_CREATE);
11928                 if (aclresult != ACLCHECK_OK)
11929                         aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
11930                                                    get_namespace_name(classform->relnamespace));
11931                 reltype = ((RenameStmt *) stmt)->renameType;
11932         }
11933         else if (IsA(stmt, AlterObjectSchemaStmt))
11934                 reltype = ((AlterObjectSchemaStmt *) stmt)->objectType;
11935
11936         else if (IsA(stmt, AlterTableStmt))
11937                 reltype = ((AlterTableStmt *) stmt)->relkind;
11938         else
11939         {
11940                 reltype = OBJECT_TABLE; /* placate compiler */
11941                 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
11942         }
11943
11944         /*
11945          * For compatibility with prior releases, we allow ALTER TABLE to be used
11946          * with most other types of relations (but not composite types). We allow
11947          * similar flexibility for ALTER INDEX in the case of RENAME, but not
11948          * otherwise.  Otherwise, the user must select the correct form of the
11949          * command for the relation at issue.
11950          */
11951         if (reltype == OBJECT_SEQUENCE && relkind != RELKIND_SEQUENCE)
11952                 ereport(ERROR,
11953                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11954                                  errmsg("\"%s\" is not a sequence", rv->relname)));
11955
11956         if (reltype == OBJECT_VIEW && relkind != RELKIND_VIEW)
11957                 ereport(ERROR,
11958                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11959                                  errmsg("\"%s\" is not a view", rv->relname)));
11960
11961         if (reltype == OBJECT_MATVIEW && relkind != RELKIND_MATVIEW)
11962                 ereport(ERROR,
11963                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11964                                  errmsg("\"%s\" is not a materialized view", rv->relname)));
11965
11966         if (reltype == OBJECT_FOREIGN_TABLE && relkind != RELKIND_FOREIGN_TABLE)
11967                 ereport(ERROR,
11968                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11969                                  errmsg("\"%s\" is not a foreign table", rv->relname)));
11970
11971         if (reltype == OBJECT_TYPE && relkind != RELKIND_COMPOSITE_TYPE)
11972                 ereport(ERROR,
11973                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11974                                  errmsg("\"%s\" is not a composite type", rv->relname)));
11975
11976         if (reltype == OBJECT_INDEX && relkind != RELKIND_INDEX
11977                 && !IsA(stmt, RenameStmt))
11978                 ereport(ERROR,
11979                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11980                                  errmsg("\"%s\" is not an index", rv->relname)));
11981
11982         /*
11983          * Don't allow ALTER TABLE on composite types. We want people to use ALTER
11984          * TYPE for that.
11985          */
11986         if (reltype != OBJECT_TYPE && relkind == RELKIND_COMPOSITE_TYPE)
11987                 ereport(ERROR,
11988                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
11989                                  errmsg("\"%s\" is a composite type", rv->relname),
11990                                  errhint("Use ALTER TYPE instead.")));
11991
11992         /*
11993          * Don't allow ALTER TABLE .. SET SCHEMA on relations that can't be moved
11994          * to a different schema, such as indexes and TOAST tables.
11995          */
11996         if (IsA(stmt, AlterObjectSchemaStmt) &&
11997                 relkind != RELKIND_RELATION &&
11998                 relkind != RELKIND_VIEW &&
11999                 relkind != RELKIND_MATVIEW &&
12000                 relkind != RELKIND_SEQUENCE &&
12001                 relkind != RELKIND_FOREIGN_TABLE)
12002                 ereport(ERROR,
12003                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
12004                                  errmsg("\"%s\" is not a table, view, materialized view, sequence, or foreign table",
12005                                                 rv->relname)));
12006
12007         ReleaseSysCache(tuple);
12008 }