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