Header And Logo

PostgreSQL
| The world's most advanced open source database.

tablecmds.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * tablecmds.c
00004  *    Commands for creating and altering table structures and settings
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/commands/tablecmds.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "access/genam.h"
00018 #include "access/heapam.h"
00019 #include "access/heapam_xlog.h"
00020 #include "access/multixact.h"
00021 #include "access/reloptions.h"
00022 #include "access/relscan.h"
00023 #include "access/sysattr.h"
00024 #include "access/xact.h"
00025 #include "catalog/catalog.h"
00026 #include "catalog/dependency.h"
00027 #include "catalog/heap.h"
00028 #include "catalog/index.h"
00029 #include "catalog/indexing.h"
00030 #include "catalog/namespace.h"
00031 #include "catalog/objectaccess.h"
00032 #include "catalog/pg_collation.h"
00033 #include "catalog/pg_constraint.h"
00034 #include "catalog/pg_depend.h"
00035 #include "catalog/pg_foreign_table.h"
00036 #include "catalog/pg_inherits.h"
00037 #include "catalog/pg_inherits_fn.h"
00038 #include "catalog/pg_namespace.h"
00039 #include "catalog/pg_opclass.h"
00040 #include "catalog/pg_tablespace.h"
00041 #include "catalog/pg_trigger.h"
00042 #include "catalog/pg_type.h"
00043 #include "catalog/pg_type_fn.h"
00044 #include "catalog/storage.h"
00045 #include "catalog/toasting.h"
00046 #include "commands/cluster.h"
00047 #include "commands/comment.h"
00048 #include "commands/defrem.h"
00049 #include "commands/sequence.h"
00050 #include "commands/tablecmds.h"
00051 #include "commands/tablespace.h"
00052 #include "commands/trigger.h"
00053 #include "commands/typecmds.h"
00054 #include "common/relpath.h"
00055 #include "executor/executor.h"
00056 #include "foreign/foreign.h"
00057 #include "miscadmin.h"
00058 #include "nodes/makefuncs.h"
00059 #include "nodes/nodeFuncs.h"
00060 #include "nodes/parsenodes.h"
00061 #include "optimizer/clauses.h"
00062 #include "optimizer/planner.h"
00063 #include "parser/parse_clause.h"
00064 #include "parser/parse_coerce.h"
00065 #include "parser/parse_collate.h"
00066 #include "parser/parse_expr.h"
00067 #include "parser/parse_oper.h"
00068 #include "parser/parse_relation.h"
00069 #include "parser/parse_type.h"
00070 #include "parser/parse_utilcmd.h"
00071 #include "parser/parser.h"
00072 #include "rewrite/rewriteDefine.h"
00073 #include "rewrite/rewriteHandler.h"
00074 #include "rewrite/rewriteManip.h"
00075 #include "storage/bufmgr.h"
00076 #include "storage/lmgr.h"
00077 #include "storage/lock.h"
00078 #include "storage/predicate.h"
00079 #include "storage/smgr.h"
00080 #include "utils/acl.h"
00081 #include "utils/builtins.h"
00082 #include "utils/fmgroids.h"
00083 #include "utils/inval.h"
00084 #include "utils/lsyscache.h"
00085 #include "utils/memutils.h"
00086 #include "utils/relcache.h"
00087 #include "utils/snapmgr.h"
00088 #include "utils/syscache.h"
00089 #include "utils/tqual.h"
00090 #include "utils/typcache.h"
00091 
00092 
00093 /*
00094  * ON COMMIT action list
00095  */
00096 typedef struct OnCommitItem
00097 {
00098     Oid         relid;          /* relid of relation */
00099     OnCommitAction oncommit;    /* what to do at end of xact */
00100 
00101     /*
00102      * If this entry was created during the current transaction,
00103      * creating_subid is the ID of the creating subxact; if created in a prior
00104      * transaction, creating_subid is zero.  If deleted during the current
00105      * transaction, deleting_subid is the ID of the deleting subxact; if no
00106      * deletion request is pending, deleting_subid is zero.
00107      */
00108     SubTransactionId creating_subid;
00109     SubTransactionId deleting_subid;
00110 } OnCommitItem;
00111 
00112 static List *on_commits = NIL;
00113 
00114 
00115 /*
00116  * State information for ALTER TABLE
00117  *
00118  * The pending-work queue for an ALTER TABLE is a List of AlteredTableInfo
00119  * structs, one for each table modified by the operation (the named table
00120  * plus any child tables that are affected).  We save lists of subcommands
00121  * to apply to this table (possibly modified by parse transformation steps);
00122  * these lists will be executed in Phase 2.  If a Phase 3 step is needed,
00123  * necessary information is stored in the constraints and newvals lists.
00124  *
00125  * Phase 2 is divided into multiple passes; subcommands are executed in
00126  * a pass determined by subcommand type.
00127  */
00128 
00129 #define AT_PASS_DROP            0       /* DROP (all flavors) */
00130 #define AT_PASS_ALTER_TYPE      1       /* ALTER COLUMN TYPE */
00131 #define AT_PASS_OLD_INDEX       2       /* re-add existing indexes */
00132 #define AT_PASS_OLD_CONSTR      3       /* re-add existing constraints */
00133 #define AT_PASS_COL_ATTRS       4       /* set other column attributes */
00134 /* We could support a RENAME COLUMN pass here, but not currently used */
00135 #define AT_PASS_ADD_COL         5       /* ADD COLUMN */
00136 #define AT_PASS_ADD_INDEX       6       /* ADD indexes */
00137 #define AT_PASS_ADD_CONSTR      7       /* ADD constraints, defaults */
00138 #define AT_PASS_MISC            8       /* other stuff */
00139 #define AT_NUM_PASSES           9
00140 
00141 typedef struct AlteredTableInfo
00142 {
00143     /* Information saved before any work commences: */
00144     Oid         relid;          /* Relation to work on */
00145     char        relkind;        /* Its relkind */
00146     TupleDesc   oldDesc;        /* Pre-modification tuple descriptor */
00147     /* Information saved by Phase 1 for Phase 2: */
00148     List       *subcmds[AT_NUM_PASSES]; /* Lists of AlterTableCmd */
00149     /* Information saved by Phases 1/2 for Phase 3: */
00150     List       *constraints;    /* List of NewConstraint */
00151     List       *newvals;        /* List of NewColumnValue */
00152     bool        new_notnull;    /* T if we added new NOT NULL constraints */
00153     bool        rewrite;        /* T if a rewrite is forced */
00154     Oid         newTableSpace;  /* new tablespace; 0 means no change */
00155     /* Objects to rebuild after completing ALTER TYPE operations */
00156     List       *changedConstraintOids;  /* OIDs of constraints to rebuild */
00157     List       *changedConstraintDefs;  /* string definitions of same */
00158     List       *changedIndexOids;       /* OIDs of indexes to rebuild */
00159     List       *changedIndexDefs;       /* string definitions of same */
00160 } AlteredTableInfo;
00161 
00162 /* Struct describing one new constraint to check in Phase 3 scan */
00163 /* Note: new NOT NULL constraints are handled elsewhere */
00164 typedef struct NewConstraint
00165 {
00166     char       *name;           /* Constraint name, or NULL if none */
00167     ConstrType  contype;        /* CHECK or FOREIGN */
00168     Oid         refrelid;       /* PK rel, if FOREIGN */
00169     Oid         refindid;       /* OID of PK's index, if FOREIGN */
00170     Oid         conid;          /* OID of pg_constraint entry, if FOREIGN */
00171     Node       *qual;           /* Check expr or CONSTR_FOREIGN Constraint */
00172     List       *qualstate;      /* Execution state for CHECK */
00173 } NewConstraint;
00174 
00175 /*
00176  * Struct describing one new column value that needs to be computed during
00177  * Phase 3 copy (this could be either a new column with a non-null default, or
00178  * a column that we're changing the type of).  Columns without such an entry
00179  * are just copied from the old table during ATRewriteTable.  Note that the
00180  * expr is an expression over *old* table values.
00181  */
00182 typedef struct NewColumnValue
00183 {
00184     AttrNumber  attnum;         /* which column */
00185     Expr       *expr;           /* expression to compute */
00186     ExprState  *exprstate;      /* execution state */
00187 } NewColumnValue;
00188 
00189 /*
00190  * Error-reporting support for RemoveRelations
00191  */
00192 struct dropmsgstrings
00193 {
00194     char        kind;
00195     int         nonexistent_code;
00196     const char *nonexistent_msg;
00197     const char *skipping_msg;
00198     const char *nota_msg;
00199     const char *drophint_msg;
00200 };
00201 
00202 static const struct dropmsgstrings dropmsgstringarray[] = {
00203     {RELKIND_RELATION,
00204         ERRCODE_UNDEFINED_TABLE,
00205         gettext_noop("table \"%s\" does not exist"),
00206         gettext_noop("table \"%s\" does not exist, skipping"),
00207         gettext_noop("\"%s\" is not a table"),
00208     gettext_noop("Use DROP TABLE to remove a table.")},
00209     {RELKIND_SEQUENCE,
00210         ERRCODE_UNDEFINED_TABLE,
00211         gettext_noop("sequence \"%s\" does not exist"),
00212         gettext_noop("sequence \"%s\" does not exist, skipping"),
00213         gettext_noop("\"%s\" is not a sequence"),
00214     gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
00215     {RELKIND_VIEW,
00216         ERRCODE_UNDEFINED_TABLE,
00217         gettext_noop("view \"%s\" does not exist"),
00218         gettext_noop("view \"%s\" does not exist, skipping"),
00219         gettext_noop("\"%s\" is not a view"),
00220     gettext_noop("Use DROP VIEW to remove a view.")},
00221     {RELKIND_MATVIEW,
00222         ERRCODE_UNDEFINED_TABLE,
00223         gettext_noop("materialized view \"%s\" does not exist"),
00224         gettext_noop("materialized view \"%s\" does not exist, skipping"),
00225         gettext_noop("\"%s\" is not a materialized view"),
00226     gettext_noop("Use DROP MATERIALIZED VIEW to remove a materialized view.")},
00227     {RELKIND_INDEX,
00228         ERRCODE_UNDEFINED_OBJECT,
00229         gettext_noop("index \"%s\" does not exist"),
00230         gettext_noop("index \"%s\" does not exist, skipping"),
00231         gettext_noop("\"%s\" is not an index"),
00232     gettext_noop("Use DROP INDEX to remove an index.")},
00233     {RELKIND_COMPOSITE_TYPE,
00234         ERRCODE_UNDEFINED_OBJECT,
00235         gettext_noop("type \"%s\" does not exist"),
00236         gettext_noop("type \"%s\" does not exist, skipping"),
00237         gettext_noop("\"%s\" is not a type"),
00238     gettext_noop("Use DROP TYPE to remove a type.")},
00239     {RELKIND_FOREIGN_TABLE,
00240         ERRCODE_UNDEFINED_OBJECT,
00241         gettext_noop("foreign table \"%s\" does not exist"),
00242         gettext_noop("foreign table \"%s\" does not exist, skipping"),
00243         gettext_noop("\"%s\" is not a foreign table"),
00244     gettext_noop("Use DROP FOREIGN TABLE to remove a foreign table.")},
00245     {'\0', 0, NULL, NULL, NULL, NULL}
00246 };
00247 
00248 struct DropRelationCallbackState
00249 {
00250     char        relkind;
00251     Oid         heapOid;
00252     bool        concurrent;
00253 };
00254 
00255 /* Alter table target-type flags for ATSimplePermissions */
00256 #define     ATT_TABLE               0x0001
00257 #define     ATT_VIEW                0x0002
00258 #define     ATT_MATVIEW             0x0004
00259 #define     ATT_INDEX               0x0008
00260 #define     ATT_COMPOSITE_TYPE      0x0010
00261 #define     ATT_FOREIGN_TABLE       0x0020
00262 
00263 static void truncate_check_rel(Relation rel);
00264 static List *MergeAttributes(List *schema, List *supers, char relpersistence,
00265                 List **supOids, List **supconstr, int *supOidCount);
00266 static bool MergeCheckConstraint(List *constraints, char *name, Node *expr);
00267 static void MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel);
00268 static void MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel);
00269 static void StoreCatalogInheritance(Oid relationId, List *supers);
00270 static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
00271                          int16 seqNumber, Relation inhRelation);
00272 static int  findAttrByName(const char *attributeName, List *schema);
00273 static void AlterIndexNamespaces(Relation classRel, Relation rel,
00274                      Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved);
00275 static void AlterSeqNamespaces(Relation classRel, Relation rel,
00276                    Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved,
00277                    LOCKMODE lockmode);
00278 static void ATExecValidateConstraint(Relation rel, char *constrName,
00279                          bool recurse, bool recursing, LOCKMODE lockmode);
00280 static int transformColumnNameList(Oid relId, List *colList,
00281                         int16 *attnums, Oid *atttypids);
00282 static int transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
00283                            List **attnamelist,
00284                            int16 *attnums, Oid *atttypids,
00285                            Oid *opclasses);
00286 static Oid transformFkeyCheckAttrs(Relation pkrel,
00287                         int numattrs, int16 *attnums,
00288                         Oid *opclasses);
00289 static void checkFkeyPermissions(Relation rel, int16 *attnums, int natts);
00290 static CoercionPathType findFkeyCast(Oid targetTypeId, Oid sourceTypeId,
00291              Oid *funcid);
00292 static void validateCheckConstraint(Relation rel, HeapTuple constrtup);
00293 static void validateForeignKeyConstraint(char *conname,
00294                              Relation rel, Relation pkrel,
00295                              Oid pkindOid, Oid constraintOid);
00296 static void createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
00297                          Oid constraintOid, Oid indexOid);
00298 static void ATController(Relation rel, List *cmds, bool recurse, LOCKMODE lockmode);
00299 static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
00300           bool recurse, bool recursing, LOCKMODE lockmode);
00301 static void ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode);
00302 static void ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
00303           AlterTableCmd *cmd, LOCKMODE lockmode);
00304 static void ATRewriteTables(List **wqueue, LOCKMODE lockmode);
00305 static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode);
00306 static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);
00307 static void ATSimplePermissions(Relation rel, int allowed_targets);
00308 static void ATWrongRelkindError(Relation rel, int allowed_targets);
00309 static void ATSimpleRecursion(List **wqueue, Relation rel,
00310                   AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode);
00311 static void ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
00312                       LOCKMODE lockmode);
00313 static List *find_typed_table_dependencies(Oid typeOid, const char *typeName,
00314                               DropBehavior behavior);
00315 static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
00316                 AlterTableCmd *cmd, LOCKMODE lockmode);
00317 static void ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
00318                 ColumnDef *colDef, bool isOid,
00319                 bool recurse, bool recursing, LOCKMODE lockmode);
00320 static void check_for_column_name_collision(Relation rel, const char *colname);
00321 static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid);
00322 static void add_column_collation_dependency(Oid relid, int32 attnum, Oid collid);
00323 static void ATPrepAddOids(List **wqueue, Relation rel, bool recurse,
00324               AlterTableCmd *cmd, LOCKMODE lockmode);
00325 static void ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode);
00326 static void ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
00327                  const char *colName, LOCKMODE lockmode);
00328 static void ATExecColumnDefault(Relation rel, const char *colName,
00329                     Node *newDefault, LOCKMODE lockmode);
00330 static void ATPrepSetStatistics(Relation rel, const char *colName,
00331                     Node *newValue, LOCKMODE lockmode);
00332 static void ATExecSetStatistics(Relation rel, const char *colName,
00333                     Node *newValue, LOCKMODE lockmode);
00334 static void ATExecSetOptions(Relation rel, const char *colName,
00335                  Node *options, bool isReset, LOCKMODE lockmode);
00336 static void ATExecSetStorage(Relation rel, const char *colName,
00337                  Node *newValue, LOCKMODE lockmode);
00338 static void ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
00339                  AlterTableCmd *cmd, LOCKMODE lockmode);
00340 static void ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
00341                  DropBehavior behavior,
00342                  bool recurse, bool recursing,
00343                  bool missing_ok, LOCKMODE lockmode);
00344 static void ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
00345                IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode);
00346 static void ATExecAddConstraint(List **wqueue,
00347                     AlteredTableInfo *tab, Relation rel,
00348                     Constraint *newConstraint, bool recurse, bool is_readd,
00349                     LOCKMODE lockmode);
00350 static void ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
00351                          IndexStmt *stmt, LOCKMODE lockmode);
00352 static void ATAddCheckConstraint(List **wqueue,
00353                      AlteredTableInfo *tab, Relation rel,
00354                      Constraint *constr,
00355                      bool recurse, bool recursing, bool is_readd,
00356                      LOCKMODE lockmode);
00357 static void ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
00358                           Constraint *fkconstraint, LOCKMODE lockmode);
00359 static void ATExecDropConstraint(Relation rel, const char *constrName,
00360                      DropBehavior behavior,
00361                      bool recurse, bool recursing,
00362                      bool missing_ok, LOCKMODE lockmode);
00363 static void ATPrepAlterColumnType(List **wqueue,
00364                       AlteredTableInfo *tab, Relation rel,
00365                       bool recurse, bool recursing,
00366                       AlterTableCmd *cmd, LOCKMODE lockmode);
00367 static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno);
00368 static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
00369                       AlterTableCmd *cmd, LOCKMODE lockmode);
00370 static void ATExecAlterColumnGenericOptions(Relation rel, const char *colName,
00371                                 List *options, LOCKMODE lockmode);
00372 static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode);
00373 static void ATPostAlterTypeParse(Oid oldId, char *cmd,
00374                      List **wqueue, LOCKMODE lockmode, bool rewrite);
00375 static void TryReuseIndex(Oid oldId, IndexStmt *stmt);
00376 static void TryReuseForeignKey(Oid oldId, Constraint *con);
00377 static void change_owner_fix_column_acls(Oid relationOid,
00378                              Oid oldOwnerId, Oid newOwnerId);
00379 static void change_owner_recurse_to_sequences(Oid relationOid,
00380                                   Oid newOwnerId, LOCKMODE lockmode);
00381 static void ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode);
00382 static void ATExecDropCluster(Relation rel, LOCKMODE lockmode);
00383 static void ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel,
00384                     char *tablespacename, LOCKMODE lockmode);
00385 static void ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode);
00386 static void ATExecSetRelOptions(Relation rel, List *defList,
00387                     AlterTableType operation,
00388                     LOCKMODE lockmode);
00389 static void ATExecEnableDisableTrigger(Relation rel, char *trigname,
00390                        char fires_when, bool skip_system, LOCKMODE lockmode);
00391 static void ATExecEnableDisableRule(Relation rel, char *rulename,
00392                         char fires_when, LOCKMODE lockmode);
00393 static void ATPrepAddInherit(Relation child_rel);
00394 static void ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode);
00395 static void ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode);
00396 static void drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid);
00397 static void ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode);
00398 static void ATExecDropOf(Relation rel, LOCKMODE lockmode);
00399 static void ATExecGenericOptions(Relation rel, List *options);
00400 
00401 static void copy_relation_data(SMgrRelation rel, SMgrRelation dst,
00402                    ForkNumber forkNum, char relpersistence);
00403 static const char *storage_name(char c);
00404 
00405 static void RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid,
00406                                 Oid oldRelOid, void *arg);
00407 static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid,
00408                                  Oid oldrelid, void *arg);
00409 
00410 
00411 /* ----------------------------------------------------------------
00412  *      DefineRelation
00413  *              Creates a new relation.
00414  *
00415  * stmt carries parsetree information from an ordinary CREATE TABLE statement.
00416  * The other arguments are used to extend the behavior for other cases:
00417  * relkind: relkind to assign to the new relation
00418  * ownerId: if not InvalidOid, use this as the new relation's owner.
00419  *
00420  * Note that permissions checks are done against current user regardless of
00421  * ownerId.  A nonzero ownerId is used when someone is creating a relation
00422  * "on behalf of" someone else, so we still want to see that the current user
00423  * has permissions to do it.
00424  *
00425  * If successful, returns the OID of the new relation.
00426  * ----------------------------------------------------------------
00427  */
00428 Oid
00429 DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
00430 {
00431     char        relname[NAMEDATALEN];
00432     Oid         namespaceId;
00433     List       *schema = stmt->tableElts;
00434     Oid         relationId;
00435     Oid         tablespaceId;
00436     Relation    rel;
00437     TupleDesc   descriptor;
00438     List       *inheritOids;
00439     List       *old_constraints;
00440     bool        localHasOids;
00441     int         parentOidCount;
00442     List       *rawDefaults;
00443     List       *cookedDefaults;
00444     Datum       reloptions;
00445     ListCell   *listptr;
00446     AttrNumber  attnum;
00447     static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
00448     Oid         ofTypeId;
00449 
00450     /*
00451      * Truncate relname to appropriate length (probably a waste of time, as
00452      * parser should have done this already).
00453      */
00454     StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);
00455 
00456     /*
00457      * Check consistency of arguments
00458      */
00459     if (stmt->oncommit != ONCOMMIT_NOOP
00460         && stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
00461         ereport(ERROR,
00462                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
00463                  errmsg("ON COMMIT can only be used on temporary tables")));
00464     if (stmt->constraints != NIL && relkind == RELKIND_FOREIGN_TABLE)
00465         ereport(ERROR,
00466                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00467                  errmsg("constraints are not supported on foreign tables")));
00468 
00469     /*
00470      * Look up the namespace in which we are supposed to create the relation,
00471      * check we have permission to create there, lock it against concurrent
00472      * drop, and mark stmt->relation as RELPERSISTENCE_TEMP if a temporary
00473      * namespace is selected.
00474      */
00475     namespaceId =
00476         RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock, NULL);
00477 
00478     /*
00479      * Security check: disallow creating temp tables from security-restricted
00480      * code.  This is needed because calling code might not expect untrusted
00481      * tables to appear in pg_temp at the front of its search path.
00482      */
00483     if (stmt->relation->relpersistence == RELPERSISTENCE_TEMP
00484         && InSecurityRestrictedOperation())
00485         ereport(ERROR,
00486                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00487                  errmsg("cannot create temporary table within security-restricted operation")));
00488 
00489     /*
00490      * Select tablespace to use.  If not specified, use default tablespace
00491      * (which may in turn default to database's default).
00492      */
00493     if (stmt->tablespacename)
00494     {
00495         tablespaceId = get_tablespace_oid(stmt->tablespacename, false);
00496     }
00497     else
00498     {
00499         tablespaceId = GetDefaultTablespace(stmt->relation->relpersistence);
00500         /* note InvalidOid is OK in this case */
00501     }
00502 
00503     /* Check permissions except when using database's default */
00504     if (OidIsValid(tablespaceId) && tablespaceId != MyDatabaseTableSpace)
00505     {
00506         AclResult   aclresult;
00507 
00508         aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),
00509                                            ACL_CREATE);
00510         if (aclresult != ACLCHECK_OK)
00511             aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
00512                            get_tablespace_name(tablespaceId));
00513     }
00514 
00515     /* In all cases disallow placing user relations in pg_global */
00516     if (tablespaceId == GLOBALTABLESPACE_OID)
00517         ereport(ERROR,
00518                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00519                  errmsg("only shared relations can be placed in pg_global tablespace")));
00520 
00521     /* Identify user ID that will own the table */
00522     if (!OidIsValid(ownerId))
00523         ownerId = GetUserId();
00524 
00525     /*
00526      * Parse and validate reloptions, if any.
00527      */
00528     reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
00529                                      true, false);
00530 
00531     (void) heap_reloptions(relkind, reloptions, true);
00532 
00533     if (stmt->ofTypename)
00534     {
00535         AclResult   aclresult;
00536 
00537         ofTypeId = typenameTypeId(NULL, stmt->ofTypename);
00538 
00539         aclresult = pg_type_aclcheck(ofTypeId, GetUserId(), ACL_USAGE);
00540         if (aclresult != ACLCHECK_OK)
00541             aclcheck_error_type(aclresult, ofTypeId);
00542     }
00543     else
00544         ofTypeId = InvalidOid;
00545 
00546     /*
00547      * Look up inheritance ancestors and generate relation schema, including
00548      * inherited attributes.
00549      */
00550     schema = MergeAttributes(schema, stmt->inhRelations,
00551                              stmt->relation->relpersistence,
00552                              &inheritOids, &old_constraints, &parentOidCount);
00553 
00554     /*
00555      * Create a tuple descriptor from the relation schema.  Note that this
00556      * deals with column names, types, and NOT NULL constraints, but not
00557      * default values or CHECK constraints; we handle those below.
00558      */
00559     descriptor = BuildDescForRelation(schema);
00560 
00561     localHasOids = interpretOidsOption(stmt->options,
00562                                        (relkind == RELKIND_RELATION ||
00563                                         relkind == RELKIND_FOREIGN_TABLE));
00564     descriptor->tdhasoid = (localHasOids || parentOidCount > 0);
00565 
00566     /*
00567      * Find columns with default values and prepare for insertion of the
00568      * defaults.  Pre-cooked (that is, inherited) defaults go into a list of
00569      * CookedConstraint structs that we'll pass to heap_create_with_catalog,
00570      * while raw defaults go into a list of RawColumnDefault structs that will
00571      * be processed by AddRelationNewConstraints.  (We can't deal with raw
00572      * expressions until we can do transformExpr.)
00573      *
00574      * We can set the atthasdef flags now in the tuple descriptor; this just
00575      * saves StoreAttrDefault from having to do an immediate update of the
00576      * pg_attribute rows.
00577      */
00578     rawDefaults = NIL;
00579     cookedDefaults = NIL;
00580     attnum = 0;
00581 
00582     foreach(listptr, schema)
00583     {
00584         ColumnDef  *colDef = lfirst(listptr);
00585 
00586         attnum++;
00587 
00588         if (colDef->raw_default != NULL)
00589         {
00590             RawColumnDefault *rawEnt;
00591 
00592             Assert(colDef->cooked_default == NULL);
00593 
00594             rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
00595             rawEnt->attnum = attnum;
00596             rawEnt->raw_default = colDef->raw_default;
00597             rawDefaults = lappend(rawDefaults, rawEnt);
00598             descriptor->attrs[attnum - 1]->atthasdef = true;
00599         }
00600         else if (colDef->cooked_default != NULL)
00601         {
00602             CookedConstraint *cooked;
00603 
00604             cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
00605             cooked->contype = CONSTR_DEFAULT;
00606             cooked->name = NULL;
00607             cooked->attnum = attnum;
00608             cooked->expr = colDef->cooked_default;
00609             cooked->skip_validation = false;
00610             cooked->is_local = true;    /* not used for defaults */
00611             cooked->inhcount = 0;       /* ditto */
00612             cooked->is_no_inherit = false;
00613             cookedDefaults = lappend(cookedDefaults, cooked);
00614             descriptor->attrs[attnum - 1]->atthasdef = true;
00615         }
00616     }
00617 
00618     /*
00619      * Create the relation.  Inherited defaults and constraints are passed in
00620      * for immediate handling --- since they don't need parsing, they can be
00621      * stored immediately.
00622      */
00623     relationId = heap_create_with_catalog(relname,
00624                                           namespaceId,
00625                                           tablespaceId,
00626                                           InvalidOid,
00627                                           InvalidOid,
00628                                           ofTypeId,
00629                                           ownerId,
00630                                           descriptor,
00631                                           list_concat(cookedDefaults,
00632                                                       old_constraints),
00633                                           relkind,
00634                                           stmt->relation->relpersistence,
00635                                           false,
00636                                           false,
00637                                           localHasOids,
00638                                           parentOidCount,
00639                                           stmt->oncommit,
00640                                           reloptions,
00641                                           true,
00642                                           allowSystemTableMods,
00643                                           false);
00644 
00645     /* Store inheritance information for new rel. */
00646     StoreCatalogInheritance(relationId, inheritOids);
00647 
00648     /*
00649      * We must bump the command counter to make the newly-created relation
00650      * tuple visible for opening.
00651      */
00652     CommandCounterIncrement();
00653 
00654     /*
00655      * Open the new relation and acquire exclusive lock on it.  This isn't
00656      * really necessary for locking out other backends (since they can't see
00657      * the new rel anyway until we commit), but it keeps the lock manager from
00658      * complaining about deadlock risks.
00659      */
00660     rel = relation_open(relationId, AccessExclusiveLock);
00661 
00662     /*
00663      * Now add any newly specified column default values and CHECK constraints
00664      * to the new relation.  These are passed to us in the form of raw
00665      * parsetrees; we need to transform them to executable expression trees
00666      * before they can be added. The most convenient way to do that is to
00667      * apply the parser's transformExpr routine, but transformExpr doesn't
00668      * work unless we have a pre-existing relation. So, the transformation has
00669      * to be postponed to this final step of CREATE TABLE.
00670      */
00671     if (rawDefaults || stmt->constraints)
00672         AddRelationNewConstraints(rel, rawDefaults, stmt->constraints,
00673                                   true, true, false);
00674 
00675     /*
00676      * Clean up.  We keep lock on new relation (although it shouldn't be
00677      * visible to anyone else anyway, until commit).
00678      */
00679     relation_close(rel, NoLock);
00680 
00681     return relationId;
00682 }
00683 
00684 /*
00685  * Emit the right error or warning message for a "DROP" command issued on a
00686  * non-existent relation
00687  */
00688 static void
00689 DropErrorMsgNonExistent(const char *relname, char rightkind, bool missing_ok)
00690 {
00691     const struct dropmsgstrings *rentry;
00692 
00693     for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
00694     {
00695         if (rentry->kind == rightkind)
00696         {
00697             if (!missing_ok)
00698             {
00699                 ereport(ERROR,
00700                         (errcode(rentry->nonexistent_code),
00701                          errmsg(rentry->nonexistent_msg, relname)));
00702             }
00703             else
00704             {
00705                 ereport(NOTICE, (errmsg(rentry->skipping_msg, relname)));
00706                 break;
00707             }
00708         }
00709     }
00710 
00711     Assert(rentry->kind != '\0');       /* Should be impossible */
00712 }
00713 
00714 /*
00715  * Emit the right error message for a "DROP" command issued on a
00716  * relation of the wrong type
00717  */
00718 static void
00719 DropErrorMsgWrongType(const char *relname, char wrongkind, char rightkind)
00720 {
00721     const struct dropmsgstrings *rentry;
00722     const struct dropmsgstrings *wentry;
00723 
00724     for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
00725         if (rentry->kind == rightkind)
00726             break;
00727     Assert(rentry->kind != '\0');
00728 
00729     for (wentry = dropmsgstringarray; wentry->kind != '\0'; wentry++)
00730         if (wentry->kind == wrongkind)
00731             break;
00732     /* wrongkind could be something we don't have in our table... */
00733 
00734     ereport(ERROR,
00735             (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00736              errmsg(rentry->nota_msg, relname),
00737        (wentry->kind != '\0') ? errhint("%s", _(wentry->drophint_msg)) : 0));
00738 }
00739 
00740 /*
00741  * RemoveRelations
00742  *      Implements DROP TABLE, DROP INDEX, DROP SEQUENCE, DROP VIEW,
00743  *      DROP MATERIALIZED VIEW, DROP FOREIGN TABLE
00744  */
00745 void
00746 RemoveRelations(DropStmt *drop)
00747 {
00748     ObjectAddresses *objects;
00749     char        relkind;
00750     ListCell   *cell;
00751     int         flags = 0;
00752     LOCKMODE    lockmode = AccessExclusiveLock;
00753 
00754     /* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */
00755     if (drop->concurrent)
00756     {
00757         flags |= PERFORM_DELETION_CONCURRENTLY;
00758         lockmode = ShareUpdateExclusiveLock;
00759         Assert(drop->removeType == OBJECT_INDEX);
00760         if (list_length(drop->objects) != 1)
00761             ereport(ERROR,
00762                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00763                      errmsg("DROP INDEX CONCURRENTLY does not support dropping multiple objects")));
00764         if (drop->behavior == DROP_CASCADE)
00765             ereport(ERROR,
00766                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00767                 errmsg("DROP INDEX CONCURRENTLY does not support CASCADE")));
00768     }
00769 
00770     /*
00771      * First we identify all the relations, then we delete them in a single
00772      * performMultipleDeletions() call.  This is to avoid unwanted DROP
00773      * RESTRICT errors if one of the relations depends on another.
00774      */
00775 
00776     /* Determine required relkind */
00777     switch (drop->removeType)
00778     {
00779         case OBJECT_TABLE:
00780             relkind = RELKIND_RELATION;
00781             break;
00782 
00783         case OBJECT_INDEX:
00784             relkind = RELKIND_INDEX;
00785             break;
00786 
00787         case OBJECT_SEQUENCE:
00788             relkind = RELKIND_SEQUENCE;
00789             break;
00790 
00791         case OBJECT_VIEW:
00792             relkind = RELKIND_VIEW;
00793             break;
00794 
00795         case OBJECT_MATVIEW:
00796             relkind = RELKIND_MATVIEW;
00797             break;
00798 
00799         case OBJECT_FOREIGN_TABLE:
00800             relkind = RELKIND_FOREIGN_TABLE;
00801             break;
00802 
00803         default:
00804             elog(ERROR, "unrecognized drop object type: %d",
00805                  (int) drop->removeType);
00806             relkind = 0;        /* keep compiler quiet */
00807             break;
00808     }
00809 
00810     /* Lock and validate each relation; build a list of object addresses */
00811     objects = new_object_addresses();
00812 
00813     foreach(cell, drop->objects)
00814     {
00815         RangeVar   *rel = makeRangeVarFromNameList((List *) lfirst(cell));
00816         Oid         relOid;
00817         ObjectAddress obj;
00818         struct DropRelationCallbackState state;
00819 
00820         /*
00821          * These next few steps are a great deal like relation_openrv, but we
00822          * don't bother building a relcache entry since we don't need it.
00823          *
00824          * Check for shared-cache-inval messages before trying to access the
00825          * relation.  This is needed to cover the case where the name
00826          * identifies a rel that has been dropped and recreated since the
00827          * start of our transaction: if we don't flush the old syscache entry,
00828          * then we'll latch onto that entry and suffer an error later.
00829          */
00830         AcceptInvalidationMessages();
00831 
00832         /* Look up the appropriate relation using namespace search. */
00833         state.relkind = relkind;
00834         state.heapOid = InvalidOid;
00835         state.concurrent = drop->concurrent;
00836         relOid = RangeVarGetRelidExtended(rel, lockmode, true,
00837                                           false,
00838                                           RangeVarCallbackForDropRelation,
00839                                           (void *) &state);
00840 
00841         /* Not there? */
00842         if (!OidIsValid(relOid))
00843         {
00844             DropErrorMsgNonExistent(rel->relname, relkind, drop->missing_ok);
00845             continue;
00846         }
00847 
00848         /* OK, we're ready to delete this one */
00849         obj.classId = RelationRelationId;
00850         obj.objectId = relOid;
00851         obj.objectSubId = 0;
00852 
00853         add_exact_object_address(&obj, objects);
00854     }
00855 
00856     performMultipleDeletions(objects, drop->behavior, flags);
00857 
00858     free_object_addresses(objects);
00859 }
00860 
00861 /*
00862  * Before acquiring a table lock, check whether we have sufficient rights.
00863  * In the case of DROP INDEX, also try to lock the table before the index.
00864  */
00865 static void
00866 RangeVarCallbackForDropRelation(const RangeVar *rel, Oid relOid, Oid oldRelOid,
00867                                 void *arg)
00868 {
00869     HeapTuple   tuple;
00870     struct DropRelationCallbackState *state;
00871     char        relkind;
00872     Form_pg_class classform;
00873     LOCKMODE    heap_lockmode;
00874 
00875     state = (struct DropRelationCallbackState *) arg;
00876     relkind = state->relkind;
00877     heap_lockmode = state->concurrent ?
00878         ShareUpdateExclusiveLock : AccessExclusiveLock;
00879 
00880     /*
00881      * If we previously locked some other index's heap, and the name we're
00882      * looking up no longer refers to that relation, release the now-useless
00883      * lock.
00884      */
00885     if (relOid != oldRelOid && OidIsValid(state->heapOid))
00886     {
00887         UnlockRelationOid(state->heapOid, heap_lockmode);
00888         state->heapOid = InvalidOid;
00889     }
00890 
00891     /* Didn't find a relation, so no need for locking or permission checks. */
00892     if (!OidIsValid(relOid))
00893         return;
00894 
00895     tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
00896     if (!HeapTupleIsValid(tuple))
00897         return;                 /* concurrently dropped, so nothing to do */
00898     classform = (Form_pg_class) GETSTRUCT(tuple);
00899 
00900     if (classform->relkind != relkind)
00901         DropErrorMsgWrongType(rel->relname, classform->relkind, relkind);
00902 
00903     /* Allow DROP to either table owner or schema owner */
00904     if (!pg_class_ownercheck(relOid, GetUserId()) &&
00905         !pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
00906         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
00907                        rel->relname);
00908 
00909     if (!allowSystemTableMods && IsSystemClass(classform))
00910         ereport(ERROR,
00911                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
00912                  errmsg("permission denied: \"%s\" is a system catalog",
00913                         rel->relname)));
00914 
00915     ReleaseSysCache(tuple);
00916 
00917     /*
00918      * In DROP INDEX, attempt to acquire lock on the parent table before
00919      * locking the index.  index_drop() will need this anyway, and since
00920      * regular queries lock tables before their indexes, we risk deadlock if
00921      * we do it the other way around.  No error if we don't find a pg_index
00922      * entry, though --- the relation may have been dropped.
00923      */
00924     if (relkind == RELKIND_INDEX && relOid != oldRelOid)
00925     {
00926         state->heapOid = IndexGetRelation(relOid, true);
00927         if (OidIsValid(state->heapOid))
00928             LockRelationOid(state->heapOid, heap_lockmode);
00929     }
00930 }
00931 
00932 /*
00933  * ExecuteTruncate
00934  *      Executes a TRUNCATE command.
00935  *
00936  * This is a multi-relation truncate.  We first open and grab exclusive
00937  * lock on all relations involved, checking permissions and otherwise
00938  * verifying that the relation is OK for truncation.  In CASCADE mode,
00939  * relations having FK references to the targeted relations are automatically
00940  * added to the group; in RESTRICT mode, we check that all FK references are
00941  * internal to the group that's being truncated.  Finally all the relations
00942  * are truncated and reindexed.
00943  */
00944 void
00945 ExecuteTruncate(TruncateStmt *stmt)
00946 {
00947     List       *rels = NIL;
00948     List       *relids = NIL;
00949     List       *seq_relids = NIL;
00950     EState     *estate;
00951     ResultRelInfo *resultRelInfos;
00952     ResultRelInfo *resultRelInfo;
00953     SubTransactionId mySubid;
00954     ListCell   *cell;
00955 
00956     /*
00957      * Open, exclusive-lock, and check all the explicitly-specified relations
00958      */
00959     foreach(cell, stmt->relations)
00960     {
00961         RangeVar   *rv = lfirst(cell);
00962         Relation    rel;
00963         bool        recurse = interpretInhOption(rv->inhOpt);
00964         Oid         myrelid;
00965 
00966         rel = heap_openrv(rv, AccessExclusiveLock);
00967         myrelid = RelationGetRelid(rel);
00968         /* don't throw error for "TRUNCATE foo, foo" */
00969         if (list_member_oid(relids, myrelid))
00970         {
00971             heap_close(rel, AccessExclusiveLock);
00972             continue;
00973         }
00974         truncate_check_rel(rel);
00975         rels = lappend(rels, rel);
00976         relids = lappend_oid(relids, myrelid);
00977 
00978         if (recurse)
00979         {
00980             ListCell   *child;
00981             List       *children;
00982 
00983             children = find_all_inheritors(myrelid, AccessExclusiveLock, NULL);
00984 
00985             foreach(child, children)
00986             {
00987                 Oid         childrelid = lfirst_oid(child);
00988 
00989                 if (list_member_oid(relids, childrelid))
00990                     continue;
00991 
00992                 /* find_all_inheritors already got lock */
00993                 rel = heap_open(childrelid, NoLock);
00994                 truncate_check_rel(rel);
00995                 rels = lappend(rels, rel);
00996                 relids = lappend_oid(relids, childrelid);
00997             }
00998         }
00999     }
01000 
01001     /*
01002      * In CASCADE mode, suck in all referencing relations as well.  This
01003      * requires multiple iterations to find indirectly-dependent relations. At
01004      * each phase, we need to exclusive-lock new rels before looking for their
01005      * dependencies, else we might miss something.  Also, we check each rel as
01006      * soon as we open it, to avoid a faux pas such as holding lock for a long
01007      * time on a rel we have no permissions for.
01008      */
01009     if (stmt->behavior == DROP_CASCADE)
01010     {
01011         for (;;)
01012         {
01013             List       *newrelids;
01014 
01015             newrelids = heap_truncate_find_FKs(relids);
01016             if (newrelids == NIL)
01017                 break;          /* nothing else to add */
01018 
01019             foreach(cell, newrelids)
01020             {
01021                 Oid         relid = lfirst_oid(cell);
01022                 Relation    rel;
01023 
01024                 rel = heap_open(relid, AccessExclusiveLock);
01025                 ereport(NOTICE,
01026                         (errmsg("truncate cascades to table \"%s\"",
01027                                 RelationGetRelationName(rel))));
01028                 truncate_check_rel(rel);
01029                 rels = lappend(rels, rel);
01030                 relids = lappend_oid(relids, relid);
01031             }
01032         }
01033     }
01034 
01035     /*
01036      * Check foreign key references.  In CASCADE mode, this should be
01037      * unnecessary since we just pulled in all the references; but as a
01038      * cross-check, do it anyway if in an Assert-enabled build.
01039      */
01040 #ifdef USE_ASSERT_CHECKING
01041     heap_truncate_check_FKs(rels, false);
01042 #else
01043     if (stmt->behavior == DROP_RESTRICT)
01044         heap_truncate_check_FKs(rels, false);
01045 #endif
01046 
01047     /*
01048      * If we are asked to restart sequences, find all the sequences, lock them
01049      * (we need AccessExclusiveLock for ResetSequence), and check permissions.
01050      * We want to do this early since it's pointless to do all the truncation
01051      * work only to fail on sequence permissions.
01052      */
01053     if (stmt->restart_seqs)
01054     {
01055         foreach(cell, rels)
01056         {
01057             Relation    rel = (Relation) lfirst(cell);
01058             List       *seqlist = getOwnedSequences(RelationGetRelid(rel));
01059             ListCell   *seqcell;
01060 
01061             foreach(seqcell, seqlist)
01062             {
01063                 Oid         seq_relid = lfirst_oid(seqcell);
01064                 Relation    seq_rel;
01065 
01066                 seq_rel = relation_open(seq_relid, AccessExclusiveLock);
01067 
01068                 /* This check must match AlterSequence! */
01069                 if (!pg_class_ownercheck(seq_relid, GetUserId()))
01070                     aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
01071                                    RelationGetRelationName(seq_rel));
01072 
01073                 seq_relids = lappend_oid(seq_relids, seq_relid);
01074 
01075                 relation_close(seq_rel, NoLock);
01076             }
01077         }
01078     }
01079 
01080     /* Prepare to catch AFTER triggers. */
01081     AfterTriggerBeginQuery();
01082 
01083     /*
01084      * To fire triggers, we'll need an EState as well as a ResultRelInfo for
01085      * each relation.  We don't need to call ExecOpenIndices, though.
01086      */
01087     estate = CreateExecutorState();
01088     resultRelInfos = (ResultRelInfo *)
01089         palloc(list_length(rels) * sizeof(ResultRelInfo));
01090     resultRelInfo = resultRelInfos;
01091     foreach(cell, rels)
01092     {
01093         Relation    rel = (Relation) lfirst(cell);
01094 
01095         InitResultRelInfo(resultRelInfo,
01096                           rel,
01097                           0,    /* dummy rangetable index */
01098                           0);
01099         resultRelInfo++;
01100     }
01101     estate->es_result_relations = resultRelInfos;
01102     estate->es_num_result_relations = list_length(rels);
01103 
01104     /*
01105      * Process all BEFORE STATEMENT TRUNCATE triggers before we begin
01106      * truncating (this is because one of them might throw an error). Also, if
01107      * we were to allow them to prevent statement execution, that would need
01108      * to be handled here.
01109      */
01110     resultRelInfo = resultRelInfos;
01111     foreach(cell, rels)
01112     {
01113         estate->es_result_relation_info = resultRelInfo;
01114         ExecBSTruncateTriggers(estate, resultRelInfo);
01115         resultRelInfo++;
01116     }
01117 
01118     /*
01119      * OK, truncate each table.
01120      */
01121     mySubid = GetCurrentSubTransactionId();
01122 
01123     foreach(cell, rels)
01124     {
01125         Relation    rel = (Relation) lfirst(cell);
01126 
01127         /*
01128          * Normally, we need a transaction-safe truncation here.  However, if
01129          * the table was either created in the current (sub)transaction or has
01130          * a new relfilenode in the current (sub)transaction, then we can just
01131          * truncate it in-place, because a rollback would cause the whole
01132          * table or the current physical file to be thrown away anyway.
01133          */
01134         if (rel->rd_createSubid == mySubid ||
01135             rel->rd_newRelfilenodeSubid == mySubid)
01136         {
01137             /* Immediate, non-rollbackable truncation is OK */
01138             heap_truncate_one_rel(rel);
01139         }
01140         else
01141         {
01142             Oid         heap_relid;
01143             Oid         toast_relid;
01144             MultiXactId minmulti;
01145 
01146             /*
01147              * This effectively deletes all rows in the table, and may be done
01148              * in a serializable transaction.  In that case we must record a
01149              * rw-conflict in to this transaction from each transaction
01150              * holding a predicate lock on the table.
01151              */
01152             CheckTableForSerializableConflictIn(rel);
01153 
01154             minmulti = GetOldestMultiXactId();
01155 
01156             /*
01157              * Need the full transaction-safe pushups.
01158              *
01159              * Create a new empty storage file for the relation, and assign it
01160              * as the relfilenode value. The old storage file is scheduled for
01161              * deletion at commit.
01162              */
01163             RelationSetNewRelfilenode(rel, RecentXmin, minmulti);
01164             if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
01165                 heap_create_init_fork(rel);
01166 
01167             heap_relid = RelationGetRelid(rel);
01168             toast_relid = rel->rd_rel->reltoastrelid;
01169 
01170             /*
01171              * The same for the toast table, if any.
01172              */
01173             if (OidIsValid(toast_relid))
01174             {
01175                 rel = relation_open(toast_relid, AccessExclusiveLock);
01176                 RelationSetNewRelfilenode(rel, RecentXmin, minmulti);
01177                 if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
01178                     heap_create_init_fork(rel);
01179                 heap_close(rel, NoLock);
01180             }
01181 
01182             /*
01183              * Reconstruct the indexes to match, and we're done.
01184              */
01185             reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST);
01186         }
01187     }
01188 
01189     /*
01190      * Restart owned sequences if we were asked to.
01191      */
01192     foreach(cell, seq_relids)
01193     {
01194         Oid         seq_relid = lfirst_oid(cell);
01195 
01196         ResetSequence(seq_relid);
01197     }
01198 
01199     /*
01200      * Process all AFTER STATEMENT TRUNCATE triggers.
01201      */
01202     resultRelInfo = resultRelInfos;
01203     foreach(cell, rels)
01204     {
01205         estate->es_result_relation_info = resultRelInfo;
01206         ExecASTruncateTriggers(estate, resultRelInfo);
01207         resultRelInfo++;
01208     }
01209 
01210     /* Handle queued AFTER triggers */
01211     AfterTriggerEndQuery(estate);
01212 
01213     /* We can clean up the EState now */
01214     FreeExecutorState(estate);
01215 
01216     /* And close the rels (can't do this while EState still holds refs) */
01217     foreach(cell, rels)
01218     {
01219         Relation    rel = (Relation) lfirst(cell);
01220 
01221         heap_close(rel, NoLock);
01222     }
01223 }
01224 
01225 /*
01226  * Check that a given rel is safe to truncate.  Subroutine for ExecuteTruncate
01227  */
01228 static void
01229 truncate_check_rel(Relation rel)
01230 {
01231     AclResult   aclresult;
01232 
01233     /* Only allow truncate on regular tables */
01234     if (rel->rd_rel->relkind != RELKIND_RELATION)
01235         ereport(ERROR,
01236                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01237                  errmsg("\"%s\" is not a table",
01238                         RelationGetRelationName(rel))));
01239 
01240     /* Permissions checks */
01241     aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
01242                                   ACL_TRUNCATE);
01243     if (aclresult != ACLCHECK_OK)
01244         aclcheck_error(aclresult, ACL_KIND_CLASS,
01245                        RelationGetRelationName(rel));
01246 
01247     if (!allowSystemTableMods && IsSystemRelation(rel))
01248         ereport(ERROR,
01249                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
01250                  errmsg("permission denied: \"%s\" is a system catalog",
01251                         RelationGetRelationName(rel))));
01252 
01253     /*
01254      * Don't allow truncate on temp tables of other backends ... their local
01255      * buffer manager is not going to cope.
01256      */
01257     if (RELATION_IS_OTHER_TEMP(rel))
01258         ereport(ERROR,
01259                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01260               errmsg("cannot truncate temporary tables of other sessions")));
01261 
01262     /*
01263      * Also check for active uses of the relation in the current transaction,
01264      * including open scans and pending AFTER trigger events.
01265      */
01266     CheckTableNotInUse(rel, "TRUNCATE");
01267 }
01268 
01269 /*
01270  * storage_name
01271  *    returns the name corresponding to a typstorage/attstorage enum value
01272  */
01273 static const char *
01274 storage_name(char c)
01275 {
01276     switch (c)
01277     {
01278         case 'p':
01279             return "PLAIN";
01280         case 'm':
01281             return "MAIN";
01282         case 'x':
01283             return "EXTENDED";
01284         case 'e':
01285             return "EXTERNAL";
01286         default:
01287             return "???";
01288     }
01289 }
01290 
01291 /*----------
01292  * MergeAttributes
01293  *      Returns new schema given initial schema and superclasses.
01294  *
01295  * Input arguments:
01296  * 'schema' is the column/attribute definition for the table. (It's a list
01297  *      of ColumnDef's.) It is destructively changed.
01298  * 'supers' is a list of names (as RangeVar nodes) of parent relations.
01299  * 'relpersistence' is a persistence type of the table.
01300  *
01301  * Output arguments:
01302  * 'supOids' receives a list of the OIDs of the parent relations.
01303  * 'supconstr' receives a list of constraints belonging to the parents,
01304  *      updated as necessary to be valid for the child.
01305  * 'supOidCount' is set to the number of parents that have OID columns.
01306  *
01307  * Return value:
01308  * Completed schema list.
01309  *
01310  * Notes:
01311  *    The order in which the attributes are inherited is very important.
01312  *    Intuitively, the inherited attributes should come first. If a table
01313  *    inherits from multiple parents, the order of those attributes are
01314  *    according to the order of the parents specified in CREATE TABLE.
01315  *
01316  *    Here's an example:
01317  *
01318  *      create table person (name text, age int4, location point);
01319  *      create table emp (salary int4, manager text) inherits(person);
01320  *      create table student (gpa float8) inherits (person);
01321  *      create table stud_emp (percent int4) inherits (emp, student);
01322  *
01323  *    The order of the attributes of stud_emp is:
01324  *
01325  *                          person {1:name, 2:age, 3:location}
01326  *                          /    \
01327  *             {6:gpa}  student   emp {4:salary, 5:manager}
01328  *                          \    /
01329  *                         stud_emp {7:percent}
01330  *
01331  *     If the same attribute name appears multiple times, then it appears
01332  *     in the result table in the proper location for its first appearance.
01333  *
01334  *     Constraints (including NOT NULL constraints) for the child table
01335  *     are the union of all relevant constraints, from both the child schema
01336  *     and parent tables.
01337  *
01338  *     The default value for a child column is defined as:
01339  *      (1) If the child schema specifies a default, that value is used.
01340  *      (2) If neither the child nor any parent specifies a default, then
01341  *          the column will not have a default.
01342  *      (3) If conflicting defaults are inherited from different parents
01343  *          (and not overridden by the child), an error is raised.
01344  *      (4) Otherwise the inherited default is used.
01345  *      Rule (3) is new in Postgres 7.1; in earlier releases you got a
01346  *      rather arbitrary choice of which parent default to use.
01347  *----------
01348  */
01349 static List *
01350 MergeAttributes(List *schema, List *supers, char relpersistence,
01351                 List **supOids, List **supconstr, int *supOidCount)
01352 {
01353     ListCell   *entry;
01354     List       *inhSchema = NIL;
01355     List       *parentOids = NIL;
01356     List       *constraints = NIL;
01357     int         parentsWithOids = 0;
01358     bool        have_bogus_defaults = false;
01359     int         child_attno;
01360     static Node bogus_marker = {0};     /* marks conflicting defaults */
01361 
01362     /*
01363      * Check for and reject tables with too many columns. We perform this
01364      * check relatively early for two reasons: (a) we don't run the risk of
01365      * overflowing an AttrNumber in subsequent code (b) an O(n^2) algorithm is
01366      * okay if we're processing <= 1600 columns, but could take minutes to
01367      * execute if the user attempts to create a table with hundreds of
01368      * thousands of columns.
01369      *
01370      * Note that we also need to check that any we do not exceed this figure
01371      * after including columns from inherited relations.
01372      */
01373     if (list_length(schema) > MaxHeapAttributeNumber)
01374         ereport(ERROR,
01375                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
01376                  errmsg("tables can have at most %d columns",
01377                         MaxHeapAttributeNumber)));
01378 
01379     /*
01380      * Check for duplicate names in the explicit list of attributes.
01381      *
01382      * Although we might consider merging such entries in the same way that we
01383      * handle name conflicts for inherited attributes, it seems to make more
01384      * sense to assume such conflicts are errors.
01385      */
01386     foreach(entry, schema)
01387     {
01388         ColumnDef  *coldef = lfirst(entry);
01389         ListCell   *rest = lnext(entry);
01390         ListCell   *prev = entry;
01391 
01392         if (coldef->typeName == NULL)
01393 
01394             /*
01395              * Typed table column option that does not belong to a column from
01396              * the type.  This works because the columns from the type come
01397              * first in the list.
01398              */
01399             ereport(ERROR,
01400                     (errcode(ERRCODE_UNDEFINED_COLUMN),
01401                      errmsg("column \"%s\" does not exist",
01402                             coldef->colname)));
01403 
01404         while (rest != NULL)
01405         {
01406             ColumnDef  *restdef = lfirst(rest);
01407             ListCell   *next = lnext(rest);     /* need to save it in case we
01408                                                  * delete it */
01409 
01410             if (strcmp(coldef->colname, restdef->colname) == 0)
01411             {
01412                 if (coldef->is_from_type)
01413                 {
01414                     /*
01415                      * merge the column options into the column from the type
01416                      */
01417                     coldef->is_not_null = restdef->is_not_null;
01418                     coldef->raw_default = restdef->raw_default;
01419                     coldef->cooked_default = restdef->cooked_default;
01420                     coldef->constraints = restdef->constraints;
01421                     coldef->is_from_type = false;
01422                     list_delete_cell(schema, rest, prev);
01423                 }
01424                 else
01425                     ereport(ERROR,
01426                             (errcode(ERRCODE_DUPLICATE_COLUMN),
01427                              errmsg("column \"%s\" specified more than once",
01428                                     coldef->colname)));
01429             }
01430             prev = rest;
01431             rest = next;
01432         }
01433     }
01434 
01435     /*
01436      * Scan the parents left-to-right, and merge their attributes to form a
01437      * list of inherited attributes (inhSchema).  Also check to see if we need
01438      * to inherit an OID column.
01439      */
01440     child_attno = 0;
01441     foreach(entry, supers)
01442     {
01443         RangeVar   *parent = (RangeVar *) lfirst(entry);
01444         Relation    relation;
01445         TupleDesc   tupleDesc;
01446         TupleConstr *constr;
01447         AttrNumber *newattno;
01448         AttrNumber  parent_attno;
01449 
01450         /*
01451          * A self-exclusive lock is needed here.  If two backends attempt to
01452          * add children to the same parent simultaneously, and that parent has
01453          * no pre-existing children, then both will attempt to update the
01454          * parent's relhassubclass field, leading to a "tuple concurrently
01455          * updated" error.  Also, this interlocks against a concurrent ANALYZE
01456          * on the parent table, which might otherwise be attempting to clear
01457          * the parent's relhassubclass field, if its previous children were
01458          * recently dropped.
01459          */
01460         relation = heap_openrv(parent, ShareUpdateExclusiveLock);
01461 
01462         if (relation->rd_rel->relkind != RELKIND_RELATION)
01463             ereport(ERROR,
01464                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01465                      errmsg("inherited relation \"%s\" is not a table",
01466                             parent->relname)));
01467         /* Permanent rels cannot inherit from temporary ones */
01468         if (relpersistence != RELPERSISTENCE_TEMP &&
01469             relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
01470             ereport(ERROR,
01471                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01472                      errmsg("cannot inherit from temporary relation \"%s\"",
01473                             parent->relname)));
01474 
01475         /* If existing rel is temp, it must belong to this session */
01476         if (relation->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
01477             !relation->rd_islocaltemp)
01478             ereport(ERROR,
01479                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01480                      errmsg("cannot inherit from temporary relation of another session")));
01481 
01482         /*
01483          * We should have an UNDER permission flag for this, but for now,
01484          * demand that creator of a child table own the parent.
01485          */
01486         if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
01487             aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
01488                            RelationGetRelationName(relation));
01489 
01490         /*
01491          * Reject duplications in the list of parents.
01492          */
01493         if (list_member_oid(parentOids, RelationGetRelid(relation)))
01494             ereport(ERROR,
01495                     (errcode(ERRCODE_DUPLICATE_TABLE),
01496              errmsg("relation \"%s\" would be inherited from more than once",
01497                     parent->relname)));
01498 
01499         parentOids = lappend_oid(parentOids, RelationGetRelid(relation));
01500 
01501         if (relation->rd_rel->relhasoids)
01502             parentsWithOids++;
01503 
01504         tupleDesc = RelationGetDescr(relation);
01505         constr = tupleDesc->constr;
01506 
01507         /*
01508          * newattno[] will contain the child-table attribute numbers for the
01509          * attributes of this parent table.  (They are not the same for
01510          * parents after the first one, nor if we have dropped columns.)
01511          */
01512         newattno = (AttrNumber *)
01513             palloc0(tupleDesc->natts * sizeof(AttrNumber));
01514 
01515         for (parent_attno = 1; parent_attno <= tupleDesc->natts;
01516              parent_attno++)
01517         {
01518             Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
01519             char       *attributeName = NameStr(attribute->attname);
01520             int         exist_attno;
01521             ColumnDef  *def;
01522 
01523             /*
01524              * Ignore dropped columns in the parent.
01525              */
01526             if (attribute->attisdropped)
01527                 continue;       /* leave newattno entry as zero */
01528 
01529             /*
01530              * Does it conflict with some previously inherited column?
01531              */
01532             exist_attno = findAttrByName(attributeName, inhSchema);
01533             if (exist_attno > 0)
01534             {
01535                 Oid         defTypeId;
01536                 int32       deftypmod;
01537                 Oid         defCollId;
01538 
01539                 /*
01540                  * Yes, try to merge the two column definitions. They must
01541                  * have the same type, typmod, and collation.
01542                  */
01543                 ereport(NOTICE,
01544                         (errmsg("merging multiple inherited definitions of column \"%s\"",
01545                                 attributeName)));
01546                 def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
01547                 typenameTypeIdAndMod(NULL, def->typeName, &defTypeId, &deftypmod);
01548                 if (defTypeId != attribute->atttypid ||
01549                     deftypmod != attribute->atttypmod)
01550                     ereport(ERROR,
01551                             (errcode(ERRCODE_DATATYPE_MISMATCH),
01552                         errmsg("inherited column \"%s\" has a type conflict",
01553                                attributeName),
01554                              errdetail("%s versus %s",
01555                                        TypeNameToString(def->typeName),
01556                                        format_type_be(attribute->atttypid))));
01557                 defCollId = GetColumnDefCollation(NULL, def, defTypeId);
01558                 if (defCollId != attribute->attcollation)
01559                     ereport(ERROR,
01560                             (errcode(ERRCODE_COLLATION_MISMATCH),
01561                     errmsg("inherited column \"%s\" has a collation conflict",
01562                            attributeName),
01563                              errdetail("\"%s\" versus \"%s\"",
01564                                        get_collation_name(defCollId),
01565                               get_collation_name(attribute->attcollation))));
01566 
01567                 /* Copy storage parameter */
01568                 if (def->storage == 0)
01569                     def->storage = attribute->attstorage;
01570                 else if (def->storage != attribute->attstorage)
01571                     ereport(ERROR,
01572                             (errcode(ERRCODE_DATATYPE_MISMATCH),
01573                              errmsg("inherited column \"%s\" has a storage parameter conflict",
01574                                     attributeName),
01575                              errdetail("%s versus %s",
01576                                        storage_name(def->storage),
01577                                        storage_name(attribute->attstorage))));
01578 
01579                 def->inhcount++;
01580                 /* Merge of NOT NULL constraints = OR 'em together */
01581                 def->is_not_null |= attribute->attnotnull;
01582                 /* Default and other constraints are handled below */
01583                 newattno[parent_attno - 1] = exist_attno;
01584             }
01585             else
01586             {
01587                 /*
01588                  * No, create a new inherited column
01589                  */
01590                 def = makeNode(ColumnDef);
01591                 def->colname = pstrdup(attributeName);
01592                 def->typeName = makeTypeNameFromOid(attribute->atttypid,
01593                                                     attribute->atttypmod);
01594                 def->inhcount = 1;
01595                 def->is_local = false;
01596                 def->is_not_null = attribute->attnotnull;
01597                 def->is_from_type = false;
01598                 def->storage = attribute->attstorage;
01599                 def->raw_default = NULL;
01600                 def->cooked_default = NULL;
01601                 def->collClause = NULL;
01602                 def->collOid = attribute->attcollation;
01603                 def->constraints = NIL;
01604                 inhSchema = lappend(inhSchema, def);
01605                 newattno[parent_attno - 1] = ++child_attno;
01606             }
01607 
01608             /*
01609              * Copy default if any
01610              */
01611             if (attribute->atthasdef)
01612             {
01613                 Node       *this_default = NULL;
01614                 AttrDefault *attrdef;
01615                 int         i;
01616 
01617                 /* Find default in constraint structure */
01618                 Assert(constr != NULL);
01619                 attrdef = constr->defval;
01620                 for (i = 0; i < constr->num_defval; i++)
01621                 {
01622                     if (attrdef[i].adnum == parent_attno)
01623                     {
01624                         this_default = stringToNode(attrdef[i].adbin);
01625                         break;
01626                     }
01627                 }
01628                 Assert(this_default != NULL);
01629 
01630                 /*
01631                  * If default expr could contain any vars, we'd need to fix
01632                  * 'em, but it can't; so default is ready to apply to child.
01633                  *
01634                  * If we already had a default from some prior parent, check
01635                  * to see if they are the same.  If so, no problem; if not,
01636                  * mark the column as having a bogus default. Below, we will
01637                  * complain if the bogus default isn't overridden by the child
01638                  * schema.
01639                  */
01640                 Assert(def->raw_default == NULL);
01641                 if (def->cooked_default == NULL)
01642                     def->cooked_default = this_default;
01643                 else if (!equal(def->cooked_default, this_default))
01644                 {
01645                     def->cooked_default = &bogus_marker;
01646                     have_bogus_defaults = true;
01647                 }
01648             }
01649         }
01650 
01651         /*
01652          * Now copy the CHECK constraints of this parent, adjusting attnos
01653          * using the completed newattno[] map.  Identically named constraints
01654          * are merged if possible, else we throw error.
01655          */
01656         if (constr && constr->num_check > 0)
01657         {
01658             ConstrCheck *check = constr->check;
01659             int         i;
01660 
01661             for (i = 0; i < constr->num_check; i++)
01662             {
01663                 char       *name = check[i].ccname;
01664                 Node       *expr;
01665                 bool        found_whole_row;
01666 
01667                 /* ignore if the constraint is non-inheritable */
01668                 if (check[i].ccnoinherit)
01669                     continue;
01670 
01671                 /* Adjust Vars to match new table's column numbering */
01672                 expr = map_variable_attnos(stringToNode(check[i].ccbin),
01673                                            1, 0,
01674                                            newattno, tupleDesc->natts,
01675                                            &found_whole_row);
01676 
01677                 /*
01678                  * For the moment we have to reject whole-row variables.
01679                  * We could convert them, if we knew the new table's rowtype
01680                  * OID, but that hasn't been assigned yet.
01681                  */
01682                 if (found_whole_row)
01683                     ereport(ERROR,
01684                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01685                              errmsg("cannot convert whole-row table reference"),
01686                              errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
01687                                        name,
01688                                        RelationGetRelationName(relation))));
01689 
01690                 /* check for duplicate */
01691                 if (!MergeCheckConstraint(constraints, name, expr))
01692                 {
01693                     /* nope, this is a new one */
01694                     CookedConstraint *cooked;
01695 
01696                     cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
01697                     cooked->contype = CONSTR_CHECK;
01698                     cooked->name = pstrdup(name);
01699                     cooked->attnum = 0; /* not used for constraints */
01700                     cooked->expr = expr;
01701                     cooked->skip_validation = false;
01702                     cooked->is_local = false;
01703                     cooked->inhcount = 1;
01704                     cooked->is_no_inherit = false;
01705                     constraints = lappend(constraints, cooked);
01706                 }
01707             }
01708         }
01709 
01710         pfree(newattno);
01711 
01712         /*
01713          * Close the parent rel, but keep our AccessShareLock on it until xact
01714          * commit.  That will prevent someone else from deleting or ALTERing
01715          * the parent before the child is committed.
01716          */
01717         heap_close(relation, NoLock);
01718     }
01719 
01720     /*
01721      * If we had no inherited attributes, the result schema is just the
01722      * explicitly declared columns.  Otherwise, we need to merge the declared
01723      * columns into the inherited schema list.
01724      */
01725     if (inhSchema != NIL)
01726     {
01727         foreach(entry, schema)
01728         {
01729             ColumnDef  *newdef = lfirst(entry);
01730             char       *attributeName = newdef->colname;
01731             int         exist_attno;
01732 
01733             /*
01734              * Does it conflict with some previously inherited column?
01735              */
01736             exist_attno = findAttrByName(attributeName, inhSchema);
01737             if (exist_attno > 0)
01738             {
01739                 ColumnDef  *def;
01740                 Oid         defTypeId,
01741                             newTypeId;
01742                 int32       deftypmod,
01743                             newtypmod;
01744                 Oid         defcollid,
01745                             newcollid;
01746 
01747                 /*
01748                  * Yes, try to merge the two column definitions. They must
01749                  * have the same type, typmod, and collation.
01750                  */
01751                 ereport(NOTICE,
01752                    (errmsg("merging column \"%s\" with inherited definition",
01753                            attributeName)));
01754                 def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
01755                 typenameTypeIdAndMod(NULL, def->typeName, &defTypeId, &deftypmod);
01756                 typenameTypeIdAndMod(NULL, newdef->typeName, &newTypeId, &newtypmod);
01757                 if (defTypeId != newTypeId || deftypmod != newtypmod)
01758                     ereport(ERROR,
01759                             (errcode(ERRCODE_DATATYPE_MISMATCH),
01760                              errmsg("column \"%s\" has a type conflict",
01761                                     attributeName),
01762                              errdetail("%s versus %s",
01763                                        TypeNameToString(def->typeName),
01764                                        TypeNameToString(newdef->typeName))));
01765                 defcollid = GetColumnDefCollation(NULL, def, defTypeId);
01766                 newcollid = GetColumnDefCollation(NULL, newdef, newTypeId);
01767                 if (defcollid != newcollid)
01768                     ereport(ERROR,
01769                             (errcode(ERRCODE_COLLATION_MISMATCH),
01770                              errmsg("column \"%s\" has a collation conflict",
01771                                     attributeName),
01772                              errdetail("\"%s\" versus \"%s\"",
01773                                        get_collation_name(defcollid),
01774                                        get_collation_name(newcollid))));
01775 
01776                 /* Copy storage parameter */
01777                 if (def->storage == 0)
01778                     def->storage = newdef->storage;
01779                 else if (newdef->storage != 0 && def->storage != newdef->storage)
01780                     ereport(ERROR,
01781                             (errcode(ERRCODE_DATATYPE_MISMATCH),
01782                      errmsg("column \"%s\" has a storage parameter conflict",
01783                             attributeName),
01784                              errdetail("%s versus %s",
01785                                        storage_name(def->storage),
01786                                        storage_name(newdef->storage))));
01787 
01788                 /* Mark the column as locally defined */
01789                 def->is_local = true;
01790                 /* Merge of NOT NULL constraints = OR 'em together */
01791                 def->is_not_null |= newdef->is_not_null;
01792                 /* If new def has a default, override previous default */
01793                 if (newdef->raw_default != NULL)
01794                 {
01795                     def->raw_default = newdef->raw_default;
01796                     def->cooked_default = newdef->cooked_default;
01797                 }
01798             }
01799             else
01800             {
01801                 /*
01802                  * No, attach new column to result schema
01803                  */
01804                 inhSchema = lappend(inhSchema, newdef);
01805             }
01806         }
01807 
01808         schema = inhSchema;
01809 
01810         /*
01811          * Check that we haven't exceeded the legal # of columns after merging
01812          * in inherited columns.
01813          */
01814         if (list_length(schema) > MaxHeapAttributeNumber)
01815             ereport(ERROR,
01816                     (errcode(ERRCODE_TOO_MANY_COLUMNS),
01817                      errmsg("tables can have at most %d columns",
01818                             MaxHeapAttributeNumber)));
01819     }
01820 
01821     /*
01822      * If we found any conflicting parent default values, check to make sure
01823      * they were overridden by the child.
01824      */
01825     if (have_bogus_defaults)
01826     {
01827         foreach(entry, schema)
01828         {
01829             ColumnDef  *def = lfirst(entry);
01830 
01831             if (def->cooked_default == &bogus_marker)
01832                 ereport(ERROR,
01833                         (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
01834                   errmsg("column \"%s\" inherits conflicting default values",
01835                          def->colname),
01836                          errhint("To resolve the conflict, specify a default explicitly.")));
01837         }
01838     }
01839 
01840     *supOids = parentOids;
01841     *supconstr = constraints;
01842     *supOidCount = parentsWithOids;
01843     return schema;
01844 }
01845 
01846 
01847 /*
01848  * MergeCheckConstraint
01849  *      Try to merge an inherited CHECK constraint with previous ones
01850  *
01851  * If we inherit identically-named constraints from multiple parents, we must
01852  * merge them, or throw an error if they don't have identical definitions.
01853  *
01854  * constraints is a list of CookedConstraint structs for previous constraints.
01855  *
01856  * Returns TRUE if merged (constraint is a duplicate), or FALSE if it's
01857  * got a so-far-unique name, or throws error if conflict.
01858  */
01859 static bool
01860 MergeCheckConstraint(List *constraints, char *name, Node *expr)
01861 {
01862     ListCell   *lc;
01863 
01864     foreach(lc, constraints)
01865     {
01866         CookedConstraint *ccon = (CookedConstraint *) lfirst(lc);
01867 
01868         Assert(ccon->contype == CONSTR_CHECK);
01869 
01870         /* Non-matching names never conflict */
01871         if (strcmp(ccon->name, name) != 0)
01872             continue;
01873 
01874         if (equal(expr, ccon->expr))
01875         {
01876             /* OK to merge */
01877             ccon->inhcount++;
01878             return true;
01879         }
01880 
01881         ereport(ERROR,
01882                 (errcode(ERRCODE_DUPLICATE_OBJECT),
01883                  errmsg("check constraint name \"%s\" appears multiple times but with different expressions",
01884                         name)));
01885     }
01886 
01887     return false;
01888 }
01889 
01890 
01891 /*
01892  * StoreCatalogInheritance
01893  *      Updates the system catalogs with proper inheritance information.
01894  *
01895  * supers is a list of the OIDs of the new relation's direct ancestors.
01896  */
01897 static void
01898 StoreCatalogInheritance(Oid relationId, List *supers)
01899 {
01900     Relation    relation;
01901     int16       seqNumber;
01902     ListCell   *entry;
01903 
01904     /*
01905      * sanity checks
01906      */
01907     AssertArg(OidIsValid(relationId));
01908 
01909     if (supers == NIL)
01910         return;
01911 
01912     /*
01913      * Store INHERITS information in pg_inherits using direct ancestors only.
01914      * Also enter dependencies on the direct ancestors, and make sure they are
01915      * marked with relhassubclass = true.
01916      *
01917      * (Once upon a time, both direct and indirect ancestors were found here
01918      * and then entered into pg_ipl.  Since that catalog doesn't exist
01919      * anymore, there's no need to look for indirect ancestors.)
01920      */
01921     relation = heap_open(InheritsRelationId, RowExclusiveLock);
01922 
01923     seqNumber = 1;
01924     foreach(entry, supers)
01925     {
01926         Oid         parentOid = lfirst_oid(entry);
01927 
01928         StoreCatalogInheritance1(relationId, parentOid, seqNumber, relation);
01929         seqNumber++;
01930     }
01931 
01932     heap_close(relation, RowExclusiveLock);
01933 }
01934 
01935 /*
01936  * Make catalog entries showing relationId as being an inheritance child
01937  * of parentOid.  inhRelation is the already-opened pg_inherits catalog.
01938  */
01939 static void
01940 StoreCatalogInheritance1(Oid relationId, Oid parentOid,
01941                          int16 seqNumber, Relation inhRelation)
01942 {
01943     TupleDesc   desc = RelationGetDescr(inhRelation);
01944     Datum       values[Natts_pg_inherits];
01945     bool        nulls[Natts_pg_inherits];
01946     ObjectAddress childobject,
01947                 parentobject;
01948     HeapTuple   tuple;
01949 
01950     /*
01951      * Make the pg_inherits entry
01952      */
01953     values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId);
01954     values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid);
01955     values[Anum_pg_inherits_inhseqno - 1] = Int16GetDatum(seqNumber);
01956 
01957     memset(nulls, 0, sizeof(nulls));
01958 
01959     tuple = heap_form_tuple(desc, values, nulls);
01960 
01961     simple_heap_insert(inhRelation, tuple);
01962 
01963     CatalogUpdateIndexes(inhRelation, tuple);
01964 
01965     heap_freetuple(tuple);
01966 
01967     /*
01968      * Store a dependency too
01969      */
01970     parentobject.classId = RelationRelationId;
01971     parentobject.objectId = parentOid;
01972     parentobject.objectSubId = 0;
01973     childobject.classId = RelationRelationId;
01974     childobject.objectId = relationId;
01975     childobject.objectSubId = 0;
01976 
01977     recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL);
01978 
01979     /*
01980      * Post creation hook of this inheritance. Since object_access_hook
01981      * doesn't take multiple object identifiers, we relay oid of parent
01982      * relation using auxiliary_id argument.
01983      */
01984     InvokeObjectPostAlterHookArg(InheritsRelationId,
01985                                  relationId, 0,
01986                                  parentOid, false);
01987 
01988     /*
01989      * Mark the parent as having subclasses.
01990      */
01991     SetRelationHasSubclass(parentOid, true);
01992 }
01993 
01994 /*
01995  * Look for an existing schema entry with the given name.
01996  *
01997  * Returns the index (starting with 1) if attribute already exists in schema,
01998  * 0 if it doesn't.
01999  */
02000 static int
02001 findAttrByName(const char *attributeName, List *schema)
02002 {
02003     ListCell   *s;
02004     int         i = 1;
02005 
02006     foreach(s, schema)
02007     {
02008         ColumnDef  *def = lfirst(s);
02009 
02010         if (strcmp(attributeName, def->colname) == 0)
02011             return i;
02012 
02013         i++;
02014     }
02015     return 0;
02016 }
02017 
02018 
02019 /*
02020  * SetRelationHasSubclass
02021  *      Set the value of the relation's relhassubclass field in pg_class.
02022  *
02023  * NOTE: caller must be holding an appropriate lock on the relation.
02024  * ShareUpdateExclusiveLock is sufficient.
02025  *
02026  * NOTE: an important side-effect of this operation is that an SI invalidation
02027  * message is sent out to all backends --- including me --- causing plans
02028  * referencing the relation to be rebuilt with the new list of children.
02029  * This must happen even if we find that no change is needed in the pg_class
02030  * row.
02031  */
02032 void
02033 SetRelationHasSubclass(Oid relationId, bool relhassubclass)
02034 {
02035     Relation    relationRelation;
02036     HeapTuple   tuple;
02037     Form_pg_class classtuple;
02038 
02039     /*
02040      * Fetch a modifiable copy of the tuple, modify it, update pg_class.
02041      */
02042     relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
02043     tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
02044     if (!HeapTupleIsValid(tuple))
02045         elog(ERROR, "cache lookup failed for relation %u", relationId);
02046     classtuple = (Form_pg_class) GETSTRUCT(tuple);
02047 
02048     if (classtuple->relhassubclass != relhassubclass)
02049     {
02050         classtuple->relhassubclass = relhassubclass;
02051         simple_heap_update(relationRelation, &tuple->t_self, tuple);
02052 
02053         /* keep the catalog indexes up to date */
02054         CatalogUpdateIndexes(relationRelation, tuple);
02055     }
02056     else
02057     {
02058         /* no need to change tuple, but force relcache rebuild anyway */
02059         CacheInvalidateRelcacheByTuple(tuple);
02060     }
02061 
02062     heap_freetuple(tuple);
02063     heap_close(relationRelation, RowExclusiveLock);
02064 }
02065 
02066 /*
02067  *      renameatt_check         - basic sanity checks before attribute rename
02068  */
02069 static void
02070 renameatt_check(Oid myrelid, Form_pg_class classform, bool recursing)
02071 {
02072     char        relkind = classform->relkind;
02073 
02074     if (classform->reloftype && !recursing)
02075         ereport(ERROR,
02076                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
02077                  errmsg("cannot rename column of typed table")));
02078 
02079     /*
02080      * Renaming the columns of sequences or toast tables doesn't actually
02081      * break anything from the system's point of view, since internal
02082      * references are by attnum.  But it doesn't seem right to allow users to
02083      * change names that are hardcoded into the system, hence the following
02084      * restriction.
02085      */
02086     if (relkind != RELKIND_RELATION &&
02087         relkind != RELKIND_VIEW &&
02088         relkind != RELKIND_MATVIEW &&
02089         relkind != RELKIND_COMPOSITE_TYPE &&
02090         relkind != RELKIND_INDEX &&
02091         relkind != RELKIND_FOREIGN_TABLE)
02092         ereport(ERROR,
02093                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
02094                  errmsg("\"%s\" is not a table, view, materialized view, composite type, index, or foreign table",
02095                         NameStr(classform->relname))));
02096 
02097     /*
02098      * permissions checking.  only the owner of a class can change its schema.
02099      */
02100     if (!pg_class_ownercheck(myrelid, GetUserId()))
02101         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
02102                        NameStr(classform->relname));
02103     if (!allowSystemTableMods && IsSystemClass(classform))
02104         ereport(ERROR,
02105                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
02106                  errmsg("permission denied: \"%s\" is a system catalog",
02107                         NameStr(classform->relname))));
02108 }
02109 
02110 /*
02111  *      renameatt_internal      - workhorse for renameatt
02112  */
02113 static void
02114 renameatt_internal(Oid myrelid,
02115                    const char *oldattname,
02116                    const char *newattname,
02117                    bool recurse,
02118                    bool recursing,
02119                    int expected_parents,
02120                    DropBehavior behavior)
02121 {
02122     Relation    targetrelation;
02123     Relation    attrelation;
02124     HeapTuple   atttup;
02125     Form_pg_attribute   attform;
02126     int         attnum;
02127 
02128     /*
02129      * Grab an exclusive lock on the target table, which we will NOT release
02130      * until end of transaction.
02131      */
02132     targetrelation = relation_open(myrelid, AccessExclusiveLock);
02133     renameatt_check(myrelid, RelationGetForm(targetrelation), recursing);
02134 
02135     /*
02136      * if the 'recurse' flag is set then we are supposed to rename this
02137      * attribute in all classes that inherit from 'relname' (as well as in
02138      * 'relname').
02139      *
02140      * any permissions or problems with duplicate attributes will cause the
02141      * whole transaction to abort, which is what we want -- all or nothing.
02142      */
02143     if (recurse)
02144     {
02145         List       *child_oids,
02146                    *child_numparents;
02147         ListCell   *lo,
02148                    *li;
02149 
02150         /*
02151          * we need the number of parents for each child so that the recursive
02152          * calls to renameatt() can determine whether there are any parents
02153          * outside the inheritance hierarchy being processed.
02154          */
02155         child_oids = find_all_inheritors(myrelid, AccessExclusiveLock,
02156                                          &child_numparents);
02157 
02158         /*
02159          * find_all_inheritors does the recursive search of the inheritance
02160          * hierarchy, so all we have to do is process all of the relids in the
02161          * list that it returns.
02162          */
02163         forboth(lo, child_oids, li, child_numparents)
02164         {
02165             Oid         childrelid = lfirst_oid(lo);
02166             int         numparents = lfirst_int(li);
02167 
02168             if (childrelid == myrelid)
02169                 continue;
02170             /* note we need not recurse again */
02171             renameatt_internal(childrelid, oldattname, newattname, false, true, numparents, behavior);
02172         }
02173     }
02174     else
02175     {
02176         /*
02177          * If we are told not to recurse, there had better not be any child
02178          * tables; else the rename would put them out of step.
02179          *
02180          * expected_parents will only be 0 if we are not already recursing.
02181          */
02182         if (expected_parents == 0 &&
02183             find_inheritance_children(myrelid, NoLock) != NIL)
02184             ereport(ERROR,
02185                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
02186                      errmsg("inherited column \"%s\" must be renamed in child tables too",
02187                             oldattname)));
02188     }
02189 
02190     /* rename attributes in typed tables of composite type */
02191     if (targetrelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
02192     {
02193         List       *child_oids;
02194         ListCell   *lo;
02195 
02196         child_oids = find_typed_table_dependencies(targetrelation->rd_rel->reltype,
02197                                      RelationGetRelationName(targetrelation),
02198                                                    behavior);
02199 
02200         foreach(lo, child_oids)
02201             renameatt_internal(lfirst_oid(lo), oldattname, newattname, true, true, 0, behavior);
02202     }
02203 
02204     attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
02205 
02206     atttup = SearchSysCacheCopyAttName(myrelid, oldattname);
02207     if (!HeapTupleIsValid(atttup))
02208         ereport(ERROR,
02209                 (errcode(ERRCODE_UNDEFINED_COLUMN),
02210                  errmsg("column \"%s\" does not exist",
02211                         oldattname)));
02212     attform = (Form_pg_attribute) GETSTRUCT(atttup);
02213 
02214     attnum = attform->attnum;
02215     if (attnum <= 0)
02216         ereport(ERROR,
02217                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02218                  errmsg("cannot rename system column \"%s\"",
02219                         oldattname)));
02220 
02221     /*
02222      * if the attribute is inherited, forbid the renaming.  if this is a
02223      * top-level call to renameatt(), then expected_parents will be 0, so the
02224      * effect of this code will be to prohibit the renaming if the attribute
02225      * is inherited at all.  if this is a recursive call to renameatt(),
02226      * expected_parents will be the number of parents the current relation has
02227      * within the inheritance hierarchy being processed, so we'll prohibit the
02228      * renaming only if there are additional parents from elsewhere.
02229      */
02230     if (attform->attinhcount > expected_parents)
02231         ereport(ERROR,
02232                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
02233                  errmsg("cannot rename inherited column \"%s\"",
02234                         oldattname)));
02235 
02236     /* new name should not already exist */
02237     check_for_column_name_collision(targetrelation, newattname);
02238 
02239     /* apply the update */
02240     namestrcpy(&(attform->attname), newattname);
02241 
02242     simple_heap_update(attrelation, &atttup->t_self, atttup);
02243 
02244     /* keep system catalog indexes current */
02245     CatalogUpdateIndexes(attrelation, atttup);
02246 
02247     InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum);
02248 
02249     heap_freetuple(atttup);
02250 
02251     heap_close(attrelation, RowExclusiveLock);
02252 
02253     relation_close(targetrelation, NoLock);     /* close rel but keep lock */
02254 }
02255 
02256 /*
02257  * Perform permissions and integrity checks before acquiring a relation lock.
02258  */
02259 static void
02260 RangeVarCallbackForRenameAttribute(const RangeVar *rv, Oid relid, Oid oldrelid,
02261                                    void *arg)
02262 {
02263     HeapTuple   tuple;
02264     Form_pg_class form;
02265 
02266     tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
02267     if (!HeapTupleIsValid(tuple))
02268         return;                 /* concurrently dropped */
02269     form = (Form_pg_class) GETSTRUCT(tuple);
02270     renameatt_check(relid, form, false);
02271     ReleaseSysCache(tuple);
02272 }
02273 
02274 /*
02275  *      renameatt       - changes the name of a attribute in a relation
02276  */
02277 Oid
02278 renameatt(RenameStmt *stmt)
02279 {
02280     Oid         relid;
02281 
02282     /* lock level taken here should match renameatt_internal */
02283     relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
02284                                      stmt->missing_ok, false,
02285                                      RangeVarCallbackForRenameAttribute,
02286                                      NULL);
02287 
02288     if (!OidIsValid(relid))
02289     {
02290         ereport(NOTICE,
02291                 (errmsg("relation \"%s\" does not exist, skipping",
02292                         stmt->relation->relname)));
02293         return InvalidOid;
02294     }
02295 
02296     renameatt_internal(relid,
02297                        stmt->subname,   /* old att name */
02298                        stmt->newname,   /* new att name */
02299                        interpretInhOption(stmt->relation->inhOpt),      /* recursive? */
02300                        false,   /* recursing? */
02301                        0,       /* expected inhcount */
02302                        stmt->behavior);
02303 
02304     /* This is an ALTER TABLE command so it's about the relid */
02305     return relid;
02306 }
02307 
02308 
02309 /*
02310  * same logic as renameatt_internal
02311  */
02312 static Oid
02313 rename_constraint_internal(Oid myrelid,
02314                            Oid mytypid,
02315                            const char *oldconname,
02316                            const char *newconname,
02317                            bool recurse,
02318                            bool recursing,
02319                            int expected_parents)
02320 {
02321     Relation    targetrelation = NULL;
02322     Oid         constraintOid;
02323     HeapTuple   tuple;
02324     Form_pg_constraint con;
02325 
02326     AssertArg(!myrelid || !mytypid);
02327 
02328     if (mytypid)
02329     {
02330         constraintOid = get_domain_constraint_oid(mytypid, oldconname, false);
02331     }
02332     else
02333     {
02334         targetrelation = relation_open(myrelid, AccessExclusiveLock);
02335 
02336         /*
02337          * don't tell it whether we're recursing; we allow changing typed
02338          * tables here
02339          */
02340         renameatt_check(myrelid, RelationGetForm(targetrelation), false);
02341 
02342         constraintOid = get_relation_constraint_oid(myrelid, oldconname, false);
02343     }
02344 
02345     tuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(constraintOid));
02346     if (!HeapTupleIsValid(tuple))
02347         elog(ERROR, "cache lookup failed for constraint %u",
02348              constraintOid);
02349     con = (Form_pg_constraint) GETSTRUCT(tuple);
02350 
02351     if (myrelid && con->contype == CONSTRAINT_CHECK && !con->connoinherit)
02352     {
02353         if (recurse)
02354         {
02355             List       *child_oids,
02356                        *child_numparents;
02357             ListCell   *lo,
02358                        *li;
02359 
02360             child_oids = find_all_inheritors(myrelid, AccessExclusiveLock,
02361                                              &child_numparents);
02362 
02363             forboth(lo, child_oids, li, child_numparents)
02364             {
02365                 Oid         childrelid = lfirst_oid(lo);
02366                 int         numparents = lfirst_int(li);
02367 
02368                 if (childrelid == myrelid)
02369                     continue;
02370 
02371                 rename_constraint_internal(childrelid, InvalidOid, oldconname, newconname, false, true, numparents);
02372             }
02373         }
02374         else
02375         {
02376             if (expected_parents == 0 &&
02377                 find_inheritance_children(myrelid, NoLock) != NIL)
02378                 ereport(ERROR,
02379                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
02380                          errmsg("inherited constraint \"%s\" must be renamed in child tables too",
02381                                 oldconname)));
02382         }
02383 
02384         if (con->coninhcount > expected_parents)
02385             ereport(ERROR,
02386                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
02387                      errmsg("cannot rename inherited constraint \"%s\"",
02388                             oldconname)));
02389     }
02390 
02391     if (con->conindid
02392         && (con->contype == CONSTRAINT_PRIMARY
02393             || con->contype == CONSTRAINT_UNIQUE
02394             || con->contype == CONSTRAINT_EXCLUSION))
02395         /* rename the index; this renames the constraint as well */
02396         RenameRelationInternal(con->conindid, newconname, false);
02397     else
02398         RenameConstraintById(constraintOid, newconname);
02399 
02400     ReleaseSysCache(tuple);
02401 
02402     if (targetrelation)
02403         relation_close(targetrelation, NoLock); /* close rel but keep lock */
02404 
02405     return constraintOid;
02406 }
02407 
02408 Oid
02409 RenameConstraint(RenameStmt *stmt)
02410 {
02411     Oid         relid = InvalidOid;
02412     Oid         typid = InvalidOid;
02413 
02414     if (stmt->relationType == OBJECT_DOMAIN)
02415     {
02416         Relation    rel;
02417         HeapTuple   tup;
02418 
02419         typid = typenameTypeId(NULL, makeTypeNameFromNameList(stmt->object));
02420         rel = heap_open(TypeRelationId, RowExclusiveLock);
02421         tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02422         if (!HeapTupleIsValid(tup))
02423             elog(ERROR, "cache lookup failed for type %u", typid);
02424         checkDomainOwner(tup);
02425         ReleaseSysCache(tup);
02426         heap_close(rel, NoLock);
02427     }
02428     else
02429     {
02430         /* lock level taken here should match rename_constraint_internal */
02431         relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
02432                                          false, false,
02433                                          RangeVarCallbackForRenameAttribute,
02434                                          NULL);
02435     }
02436 
02437     return
02438         rename_constraint_internal(relid, typid,
02439                                    stmt->subname,
02440                                    stmt->newname,
02441                                    stmt->relation ? interpretInhOption(stmt->relation->inhOpt) : false, /* recursive? */
02442                                    false,   /* recursing? */
02443                                    0 /* expected inhcount */ );
02444 
02445 }
02446 
02447 /*
02448  * Execute ALTER TABLE/INDEX/SEQUENCE/VIEW/FOREIGN TABLE RENAME
02449  */
02450 Oid
02451 RenameRelation(RenameStmt *stmt)
02452 {
02453     Oid         relid;
02454 
02455     /*
02456      * Grab an exclusive lock on the target table, index, sequence or view,
02457      * which we will NOT release until end of transaction.
02458      *
02459      * Lock level used here should match RenameRelationInternal, to avoid lock
02460      * escalation.
02461      */
02462     relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
02463                                      stmt->missing_ok, false,
02464                                      RangeVarCallbackForAlterRelation,
02465                                      (void *) stmt);
02466 
02467     if (!OidIsValid(relid))
02468     {
02469         ereport(NOTICE,
02470                 (errmsg("relation \"%s\" does not exist, skipping",
02471                         stmt->relation->relname)));
02472         return InvalidOid;
02473     }
02474 
02475     /* Do the work */
02476     RenameRelationInternal(relid, stmt->newname, false);
02477 
02478     return relid;
02479 }
02480 
02481 /*
02482  *      RenameRelationInternal - change the name of a relation
02483  *
02484  *      XXX - When renaming sequences, we don't bother to modify the
02485  *            sequence name that is stored within the sequence itself
02486  *            (this would cause problems with MVCC). In the future,
02487  *            the sequence name should probably be removed from the
02488  *            sequence, AFAIK there's no need for it to be there.
02489  */
02490 void
02491 RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
02492 {
02493     Relation    targetrelation;
02494     Relation    relrelation;    /* for RELATION relation */
02495     HeapTuple   reltup;
02496     Form_pg_class relform;
02497     Oid         namespaceId;
02498 
02499     /*
02500      * Grab an exclusive lock on the target table, index, sequence or view,
02501      * which we will NOT release until end of transaction.
02502      */
02503     targetrelation = relation_open(myrelid, AccessExclusiveLock);
02504     namespaceId = RelationGetNamespace(targetrelation);
02505 
02506     /*
02507      * Find relation's pg_class tuple, and make sure newrelname isn't in use.
02508      */
02509     relrelation = heap_open(RelationRelationId, RowExclusiveLock);
02510 
02511     reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
02512     if (!HeapTupleIsValid(reltup))      /* shouldn't happen */
02513         elog(ERROR, "cache lookup failed for relation %u", myrelid);
02514     relform = (Form_pg_class) GETSTRUCT(reltup);
02515 
02516     if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
02517         ereport(ERROR,
02518                 (errcode(ERRCODE_DUPLICATE_TABLE),
02519                  errmsg("relation \"%s\" already exists",
02520                         newrelname)));
02521 
02522     /*
02523      * Update pg_class tuple with new relname.  (Scribbling on reltup is OK
02524      * because it's a copy...)
02525      */
02526     namestrcpy(&(relform->relname), newrelname);
02527 
02528     simple_heap_update(relrelation, &reltup->t_self, reltup);
02529 
02530     /* keep the system catalog indexes current */
02531     CatalogUpdateIndexes(relrelation, reltup);
02532 
02533     InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0,
02534                                  InvalidOid, is_internal);
02535 
02536     heap_freetuple(reltup);
02537     heap_close(relrelation, RowExclusiveLock);
02538 
02539     /*
02540      * Also rename the associated type, if any.
02541      */
02542     if (OidIsValid(targetrelation->rd_rel->reltype))
02543         RenameTypeInternal(targetrelation->rd_rel->reltype,
02544                            newrelname, namespaceId);
02545 
02546     /*
02547      * Also rename the associated constraint, if any.
02548      */
02549     if (targetrelation->rd_rel->relkind == RELKIND_INDEX)
02550     {
02551         Oid         constraintId = get_index_constraint(myrelid);
02552 
02553         if (OidIsValid(constraintId))
02554             RenameConstraintById(constraintId, newrelname);
02555     }
02556 
02557     /*
02558      * Close rel, but keep exclusive lock!
02559      */
02560     relation_close(targetrelation, NoLock);
02561 }
02562 
02563 /*
02564  * Disallow ALTER TABLE (and similar commands) when the current backend has
02565  * any open reference to the target table besides the one just acquired by
02566  * the calling command; this implies there's an open cursor or active plan.
02567  * We need this check because our lock doesn't protect us against stomping
02568  * on our own foot, only other people's feet!
02569  *
02570  * For ALTER TABLE, the only case known to cause serious trouble is ALTER
02571  * COLUMN TYPE, and some changes are obviously pretty benign, so this could
02572  * possibly be relaxed to only error out for certain types of alterations.
02573  * But the use-case for allowing any of these things is not obvious, so we
02574  * won't work hard at it for now.
02575  *
02576  * We also reject these commands if there are any pending AFTER trigger events
02577  * for the rel.  This is certainly necessary for the rewriting variants of
02578  * ALTER TABLE, because they don't preserve tuple TIDs and so the pending
02579  * events would try to fetch the wrong tuples.  It might be overly cautious
02580  * in other cases, but again it seems better to err on the side of paranoia.
02581  *
02582  * REINDEX calls this with "rel" referencing the index to be rebuilt; here
02583  * we are worried about active indexscans on the index.  The trigger-event
02584  * check can be skipped, since we are doing no damage to the parent table.
02585  *
02586  * The statement name (eg, "ALTER TABLE") is passed for use in error messages.
02587  */
02588 void
02589 CheckTableNotInUse(Relation rel, const char *stmt)
02590 {
02591     int         expected_refcnt;
02592 
02593     expected_refcnt = rel->rd_isnailed ? 2 : 1;
02594     if (rel->rd_refcnt != expected_refcnt)
02595         ereport(ERROR,
02596                 (errcode(ERRCODE_OBJECT_IN_USE),
02597         /* translator: first %s is a SQL command, eg ALTER TABLE */
02598                  errmsg("cannot %s \"%s\" because "
02599                         "it is being used by active queries in this session",
02600                         stmt, RelationGetRelationName(rel))));
02601 
02602     if (rel->rd_rel->relkind != RELKIND_INDEX &&
02603         AfterTriggerPendingOnRel(RelationGetRelid(rel)))
02604         ereport(ERROR,
02605                 (errcode(ERRCODE_OBJECT_IN_USE),
02606         /* translator: first %s is a SQL command, eg ALTER TABLE */
02607                  errmsg("cannot %s \"%s\" because "
02608                         "it has pending trigger events",
02609                         stmt, RelationGetRelationName(rel))));
02610 }
02611 
02612 /*
02613  * AlterTableLookupRelation
02614  *      Look up, and lock, the OID for the relation named by an alter table
02615  *      statement.
02616  */
02617 Oid
02618 AlterTableLookupRelation(AlterTableStmt *stmt, LOCKMODE lockmode)
02619 {
02620     return RangeVarGetRelidExtended(stmt->relation, lockmode, stmt->missing_ok, false,
02621                                     RangeVarCallbackForAlterRelation,
02622                                     (void *) stmt);
02623 }
02624 
02625 /*
02626  * AlterTable
02627  *      Execute ALTER TABLE, which can be a list of subcommands
02628  *
02629  * ALTER TABLE is performed in three phases:
02630  *      1. Examine subcommands and perform pre-transformation checking.
02631  *      2. Update system catalogs.
02632  *      3. Scan table(s) to check new constraints, and optionally recopy
02633  *         the data into new table(s).
02634  * Phase 3 is not performed unless one or more of the subcommands requires
02635  * it.  The intention of this design is to allow multiple independent
02636  * updates of the table schema to be performed with only one pass over the
02637  * data.
02638  *
02639  * ATPrepCmd performs phase 1.  A "work queue" entry is created for
02640  * each table to be affected (there may be multiple affected tables if the
02641  * commands traverse a table inheritance hierarchy).  Also we do preliminary
02642  * validation of the subcommands, including parse transformation of those
02643  * expressions that need to be evaluated with respect to the old table
02644  * schema.
02645  *
02646  * ATRewriteCatalogs performs phase 2 for each affected table.  (Note that
02647  * phases 2 and 3 normally do no explicit recursion, since phase 1 already
02648  * did it --- although some subcommands have to recurse in phase 2 instead.)
02649  * Certain subcommands need to be performed before others to avoid
02650  * unnecessary conflicts; for example, DROP COLUMN should come before
02651  * ADD COLUMN.  Therefore phase 1 divides the subcommands into multiple
02652  * lists, one for each logical "pass" of phase 2.
02653  *
02654  * ATRewriteTables performs phase 3 for those tables that need it.
02655  *
02656  * Thanks to the magic of MVCC, an error anywhere along the way rolls back
02657  * the whole operation; we don't have to do anything special to clean up.
02658  *
02659  * The caller must lock the relation, with an appropriate lock level
02660  * for the subcommands requested. Any subcommand that needs to rewrite
02661  * tuples in the table forces the whole command to be executed with
02662  * AccessExclusiveLock (actually, that is currently required always, but
02663  * we hope to relax it at some point).  We pass the lock level down
02664  * so that we can apply it recursively to inherited tables. Note that the
02665  * lock level we want as we recurse might well be higher than required for
02666  * that specific subcommand. So we pass down the overall lock requirement,
02667  * rather than reassess it at lower levels.
02668  */
02669 void
02670 AlterTable(Oid relid, LOCKMODE lockmode, AlterTableStmt *stmt)
02671 {
02672     Relation    rel;
02673 
02674     /* Caller is required to provide an adequate lock. */
02675     rel = relation_open(relid, NoLock);
02676 
02677     CheckTableNotInUse(rel, "ALTER TABLE");
02678 
02679     ATController(rel, stmt->cmds, interpretInhOption(stmt->relation->inhOpt),
02680                  lockmode);
02681 }
02682 
02683 /*
02684  * AlterTableInternal
02685  *
02686  * ALTER TABLE with target specified by OID
02687  *
02688  * We do not reject if the relation is already open, because it's quite
02689  * likely that one or more layers of caller have it open.  That means it
02690  * is unsafe to use this entry point for alterations that could break
02691  * existing query plans.  On the assumption it's not used for such, we
02692  * don't have to reject pending AFTER triggers, either.
02693  */
02694 void
02695 AlterTableInternal(Oid relid, List *cmds, bool recurse)
02696 {
02697     Relation    rel;
02698     LOCKMODE    lockmode = AlterTableGetLockLevel(cmds);
02699 
02700     rel = relation_open(relid, lockmode);
02701 
02702     ATController(rel, cmds, recurse, lockmode);
02703 }
02704 
02705 /*
02706  * AlterTableGetLockLevel
02707  *
02708  * Sets the overall lock level required for the supplied list of subcommands.
02709  * Policy for doing this set according to needs of AlterTable(), see
02710  * comments there for overall explanation.
02711  *
02712  * Function is called before and after parsing, so it must give same
02713  * answer each time it is called. Some subcommands are transformed
02714  * into other subcommand types, so the transform must never be made to a
02715  * lower lock level than previously assigned. All transforms are noted below.
02716  *
02717  * Since this is called before we lock the table we cannot use table metadata
02718  * to influence the type of lock we acquire.
02719  *
02720  * There should be no lockmodes hardcoded into the subcommand functions. All
02721  * lockmode decisions for ALTER TABLE are made here only. The one exception is
02722  * ALTER TABLE RENAME which is treated as a different statement type T_RenameStmt
02723  * and does not travel through this section of code and cannot be combined with
02724  * any of the subcommands given here.
02725  */
02726 LOCKMODE
02727 AlterTableGetLockLevel(List *cmds)
02728 {
02729     /*
02730      * Late in 9.1 dev cycle a number of issues were uncovered with access to
02731      * catalog relations, leading to the decision to re-enforce all DDL at
02732      * AccessExclusiveLock level by default.
02733      *
02734      * The issues are that there is a pervasive assumption in the code that
02735      * the catalogs will not be read unless an AccessExclusiveLock is held. If
02736      * that rule is relaxed, we must protect against a number of potential
02737      * effects - infrequent, but proven possible with test cases where
02738      * multiple DDL operations occur in a stream against frequently accessed
02739      * tables.
02740      *
02741      * 1. Catalog tables are read using SnapshotNow, which has a race bug that
02742      * allows a scan to return no valid rows even when one is present in the
02743      * case of a commit of a concurrent update of the catalog table.
02744      * SnapshotNow also ignores transactions in progress, so takes the latest
02745      * committed version without waiting for the latest changes.
02746      *
02747      * 2. Relcache needs to be internally consistent, so unless we lock the
02748      * definition during reads we have no way to guarantee that.
02749      *
02750      * 3. Catcache access isn't coordinated at all so refreshes can occur at
02751      * any time.
02752      */
02753 #ifdef REDUCED_ALTER_TABLE_LOCK_LEVELS
02754     ListCell   *lcmd;
02755     LOCKMODE    lockmode = ShareUpdateExclusiveLock;
02756 
02757     foreach(lcmd, cmds)
02758     {
02759         AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
02760         LOCKMODE    cmd_lockmode = AccessExclusiveLock; /* default for compiler */
02761 
02762         switch (cmd->subtype)
02763         {
02764                 /*
02765                  * Need AccessExclusiveLock for these subcommands because they
02766                  * affect or potentially affect both read and write
02767                  * operations.
02768                  *
02769                  * New subcommand types should be added here by default.
02770                  */
02771             case AT_AddColumn:  /* may rewrite heap, in some cases and visible
02772                                  * to SELECT */
02773             case AT_DropColumn: /* change visible to SELECT */
02774             case AT_AddColumnToView:    /* CREATE VIEW */
02775             case AT_AlterColumnType:    /* must rewrite heap */
02776             case AT_DropConstraint:     /* as DROP INDEX */
02777             case AT_AddOids:    /* must rewrite heap */
02778             case AT_DropOids:   /* calls AT_DropColumn */
02779             case AT_EnableAlwaysRule:   /* may change SELECT rules */
02780             case AT_EnableReplicaRule:  /* may change SELECT rules */
02781             case AT_EnableRule: /* may change SELECT rules */
02782             case AT_DisableRule:        /* may change SELECT rules */
02783             case AT_ChangeOwner:        /* change visible to SELECT */
02784             case AT_SetTableSpace:      /* must rewrite heap */
02785             case AT_DropNotNull:        /* may change some SQL plans */
02786             case AT_SetNotNull:
02787             case AT_GenericOptions:
02788             case AT_AlterColumnGenericOptions:
02789                 cmd_lockmode = AccessExclusiveLock;
02790                 break;
02791 
02792                 /*
02793                  * These subcommands affect write operations only.
02794                  */
02795             case AT_ColumnDefault:
02796             case AT_ProcessedConstraint:        /* becomes AT_AddConstraint */
02797             case AT_AddConstraintRecurse:       /* becomes AT_AddConstraint */
02798             case AT_ReAddConstraint:            /* becomes AT_AddConstraint */
02799             case AT_EnableTrig:
02800             case AT_EnableAlwaysTrig:
02801             case AT_EnableReplicaTrig:
02802             case AT_EnableTrigAll:
02803             case AT_EnableTrigUser:
02804             case AT_DisableTrig:
02805             case AT_DisableTrigAll:
02806             case AT_DisableTrigUser:
02807             case AT_AddIndex:   /* from ADD CONSTRAINT */
02808             case AT_AddIndexConstraint:
02809                 cmd_lockmode = ShareRowExclusiveLock;
02810                 break;
02811 
02812             case AT_AddConstraint:
02813                 if (IsA(cmd->def, Constraint))
02814                 {
02815                     Constraint *con = (Constraint *) cmd->def;
02816 
02817                     switch (con->contype)
02818                     {
02819                         case CONSTR_EXCLUSION:
02820                         case CONSTR_PRIMARY:
02821                         case CONSTR_UNIQUE:
02822 
02823                             /*
02824                              * Cases essentially the same as CREATE INDEX. We
02825                              * could reduce the lock strength to ShareLock if
02826                              * we can work out how to allow concurrent catalog
02827                              * updates.
02828                              */
02829                             cmd_lockmode = ShareRowExclusiveLock;
02830                             break;
02831                         case CONSTR_FOREIGN:
02832 
02833                             /*
02834                              * We add triggers to both tables when we add a
02835                              * Foreign Key, so the lock level must be at least
02836                              * as strong as CREATE TRIGGER.
02837                              */
02838                             cmd_lockmode = ShareRowExclusiveLock;
02839                             break;
02840 
02841                         default:
02842                             cmd_lockmode = ShareRowExclusiveLock;
02843                     }
02844                 }
02845                 break;
02846 
02847                 /*
02848                  * These subcommands affect inheritance behaviour. Queries
02849                  * started before us will continue to see the old inheritance
02850                  * behaviour, while queries started after we commit will see
02851                  * new behaviour. No need to prevent reads or writes to the
02852                  * subtable while we hook it up though.
02853                  */
02854             case AT_AddInherit:
02855             case AT_DropInherit:
02856                 cmd_lockmode = ShareUpdateExclusiveLock;
02857                 break;
02858 
02859                 /*
02860                  * These subcommands affect implicit row type conversion. They
02861                  * have affects similar to CREATE/DROP CAST on queries.  We
02862                  * don't provide for invalidating parse trees as a result of
02863                  * such changes.  Do avoid concurrent pg_class updates,
02864                  * though.
02865                  */
02866             case AT_AddOf:
02867             case AT_DropOf:
02868                 cmd_lockmode = ShareUpdateExclusiveLock;
02869 
02870                 /*
02871                  * These subcommands affect general strategies for performance
02872                  * and maintenance, though don't change the semantic results
02873                  * from normal data reads and writes. Delaying an ALTER TABLE
02874                  * behind currently active writes only delays the point where
02875                  * the new strategy begins to take effect, so there is no
02876                  * benefit in waiting. In this case the minimum restriction
02877                  * applies: we don't currently allow concurrent catalog
02878                  * updates.
02879                  */
02880             case AT_SetStatistics:
02881             case AT_ClusterOn:
02882             case AT_DropCluster:
02883             case AT_SetRelOptions:
02884             case AT_ResetRelOptions:
02885             case AT_ReplaceRelOptions:
02886             case AT_SetOptions:
02887             case AT_ResetOptions:
02888             case AT_SetStorage:
02889             case AT_ValidateConstraint:
02890                 cmd_lockmode = ShareUpdateExclusiveLock;
02891                 break;
02892 
02893             default:            /* oops */
02894                 elog(ERROR, "unrecognized alter table type: %d",
02895                      (int) cmd->subtype);
02896                 break;
02897         }
02898 
02899         /*
02900          * Take the greatest lockmode from any subcommand
02901          */
02902         if (cmd_lockmode > lockmode)
02903             lockmode = cmd_lockmode;
02904     }
02905 #else
02906     LOCKMODE    lockmode = AccessExclusiveLock;
02907 #endif
02908 
02909     return lockmode;
02910 }
02911 
02912 static void
02913 ATController(Relation rel, List *cmds, bool recurse, LOCKMODE lockmode)
02914 {
02915     List       *wqueue = NIL;
02916     ListCell   *lcmd;
02917 
02918     /* Phase 1: preliminary examination of commands, create work queue */
02919     foreach(lcmd, cmds)
02920     {
02921         AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
02922 
02923         ATPrepCmd(&wqueue, rel, cmd, recurse, false, lockmode);
02924     }
02925 
02926     /* Close the relation, but keep lock until commit */
02927     relation_close(rel, NoLock);
02928 
02929     /* Phase 2: update system catalogs */
02930     ATRewriteCatalogs(&wqueue, lockmode);
02931 
02932     /* Phase 3: scan/rewrite tables as needed */
02933     ATRewriteTables(&wqueue, lockmode);
02934 }
02935 
02936 /*
02937  * ATPrepCmd
02938  *
02939  * Traffic cop for ALTER TABLE Phase 1 operations, including simple
02940  * recursion and permission checks.
02941  *
02942  * Caller must have acquired appropriate lock type on relation already.
02943  * This lock should be held until commit.
02944  */
02945 static void
02946 ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
02947           bool recurse, bool recursing, LOCKMODE lockmode)
02948 {
02949     AlteredTableInfo *tab;
02950     int         pass;
02951 
02952     /* Find or create work queue entry for this table */
02953     tab = ATGetQueueEntry(wqueue, rel);
02954 
02955     /*
02956      * Copy the original subcommand for each table.  This avoids conflicts
02957      * when different child tables need to make different parse
02958      * transformations (for example, the same column may have different column
02959      * numbers in different children).
02960      */
02961     cmd = copyObject(cmd);
02962 
02963     /*
02964      * Do permissions checking, recursion to child tables if needed, and any
02965      * additional phase-1 processing needed.
02966      */
02967     switch (cmd->subtype)
02968     {
02969         case AT_AddColumn:      /* ADD COLUMN */
02970             ATSimplePermissions(rel,
02971                          ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
02972             ATPrepAddColumn(wqueue, rel, recurse, recursing, cmd, lockmode);
02973             /* Recursion occurs during execution phase */
02974             pass = AT_PASS_ADD_COL;
02975             break;
02976         case AT_AddColumnToView:        /* add column via CREATE OR REPLACE
02977                                          * VIEW */
02978             ATSimplePermissions(rel, ATT_VIEW);
02979             ATPrepAddColumn(wqueue, rel, recurse, recursing, cmd, lockmode);
02980             /* Recursion occurs during execution phase */
02981             pass = AT_PASS_ADD_COL;
02982             break;
02983         case AT_ColumnDefault:  /* ALTER COLUMN DEFAULT */
02984 
02985             /*
02986              * We allow defaults on views so that INSERT into a view can have
02987              * default-ish behavior.  This works because the rewriter
02988              * substitutes default values into INSERTs before it expands
02989              * rules.
02990              */
02991             ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_FOREIGN_TABLE);
02992             ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
02993             /* No command-specific prep needed */
02994             pass = cmd->def ? AT_PASS_ADD_CONSTR : AT_PASS_DROP;
02995             break;
02996         case AT_DropNotNull:    /* ALTER COLUMN DROP NOT NULL */
02997             ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
02998             ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
02999             /* No command-specific prep needed */
03000             pass = AT_PASS_DROP;
03001             break;
03002         case AT_SetNotNull:     /* ALTER COLUMN SET NOT NULL */
03003             ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
03004             ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
03005             /* No command-specific prep needed */
03006             pass = AT_PASS_ADD_CONSTR;
03007             break;
03008         case AT_SetStatistics:  /* ALTER COLUMN SET STATISTICS */
03009             ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
03010             /* Performs own permission checks */
03011             ATPrepSetStatistics(rel, cmd->name, cmd->def, lockmode);
03012             pass = AT_PASS_MISC;
03013             break;
03014         case AT_SetOptions:     /* ALTER COLUMN SET ( options ) */
03015         case AT_ResetOptions:   /* ALTER COLUMN RESET ( options ) */
03016             ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_FOREIGN_TABLE);
03017             /* This command never recurses */
03018             pass = AT_PASS_MISC;
03019             break;
03020         case AT_SetStorage:     /* ALTER COLUMN SET STORAGE */
03021             ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW);
03022             ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
03023             /* No command-specific prep needed */
03024             pass = AT_PASS_MISC;
03025             break;
03026         case AT_DropColumn:     /* DROP COLUMN */
03027             ATSimplePermissions(rel,
03028                          ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
03029             ATPrepDropColumn(wqueue, rel, recurse, recursing, cmd, lockmode);
03030             /* Recursion occurs during execution phase */
03031             pass = AT_PASS_DROP;
03032             break;
03033         case AT_AddIndex:       /* ADD INDEX */
03034             ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW);
03035             /* This command never recurses */
03036             /* No command-specific prep needed */
03037             pass = AT_PASS_ADD_INDEX;
03038             break;
03039         case AT_AddConstraint:  /* ADD CONSTRAINT */
03040             ATSimplePermissions(rel, ATT_TABLE);
03041             /* Recursion occurs during execution phase */
03042             /* No command-specific prep needed except saving recurse flag */
03043             if (recurse)
03044                 cmd->subtype = AT_AddConstraintRecurse;
03045             pass = AT_PASS_ADD_CONSTR;
03046             break;
03047         case AT_AddIndexConstraint:     /* ADD CONSTRAINT USING INDEX */
03048             ATSimplePermissions(rel, ATT_TABLE);
03049             /* This command never recurses */
03050             /* No command-specific prep needed */
03051             pass = AT_PASS_ADD_CONSTR;
03052             break;
03053         case AT_DropConstraint: /* DROP CONSTRAINT */
03054             ATSimplePermissions(rel, ATT_TABLE);
03055             /* Recursion occurs during execution phase */
03056             /* No command-specific prep needed except saving recurse flag */
03057             if (recurse)
03058                 cmd->subtype = AT_DropConstraintRecurse;
03059             pass = AT_PASS_DROP;
03060             break;
03061         case AT_AlterColumnType:        /* ALTER COLUMN TYPE */
03062             ATSimplePermissions(rel,
03063                          ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE);
03064             /* Performs own recursion */
03065             ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd, lockmode);
03066             pass = AT_PASS_ALTER_TYPE;
03067             break;
03068         case AT_AlterColumnGenericOptions:
03069             ATSimplePermissions(rel, ATT_FOREIGN_TABLE);
03070             /* This command never recurses */
03071             /* No command-specific prep needed */
03072             pass = AT_PASS_MISC;
03073             break;
03074         case AT_ChangeOwner:    /* ALTER OWNER */
03075             /* This command never recurses */
03076             /* No command-specific prep needed */
03077             pass = AT_PASS_MISC;
03078             break;
03079         case AT_ClusterOn:      /* CLUSTER ON */
03080         case AT_DropCluster:    /* SET WITHOUT CLUSTER */
03081             ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW);
03082             /* These commands never recurse */
03083             /* No command-specific prep needed */
03084             pass = AT_PASS_MISC;
03085             break;
03086         case AT_AddOids:        /* SET WITH OIDS */
03087             ATSimplePermissions(rel, ATT_TABLE);
03088             if (!rel->rd_rel->relhasoids || recursing)
03089                 ATPrepAddOids(wqueue, rel, recurse, cmd, lockmode);
03090             /* Recursion occurs during execution phase */
03091             pass = AT_PASS_ADD_COL;
03092             break;
03093         case AT_DropOids:       /* SET WITHOUT OIDS */
03094             ATSimplePermissions(rel, ATT_TABLE);
03095             /* Performs own recursion */
03096             if (rel->rd_rel->relhasoids)
03097             {
03098                 AlterTableCmd *dropCmd = makeNode(AlterTableCmd);
03099 
03100                 dropCmd->subtype = AT_DropColumn;
03101                 dropCmd->name = pstrdup("oid");
03102                 dropCmd->behavior = cmd->behavior;
03103                 ATPrepCmd(wqueue, rel, dropCmd, recurse, false, lockmode);
03104             }
03105             pass = AT_PASS_DROP;
03106             break;
03107         case AT_SetTableSpace:  /* SET TABLESPACE */
03108             ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX);
03109             /* This command never recurses */
03110             ATPrepSetTableSpace(tab, rel, cmd->name, lockmode);
03111             pass = AT_PASS_MISC;    /* doesn't actually matter */
03112             break;
03113         case AT_SetRelOptions:  /* SET (...) */
03114         case AT_ResetRelOptions:        /* RESET (...) */
03115         case AT_ReplaceRelOptions:      /* reset them all, then set just these */
03116             ATSimplePermissions(rel, ATT_TABLE | ATT_VIEW | ATT_MATVIEW | ATT_INDEX);
03117             /* This command never recurses */
03118             /* No command-specific prep needed */
03119             pass = AT_PASS_MISC;
03120             break;
03121         case AT_AddInherit:     /* INHERIT */
03122             ATSimplePermissions(rel, ATT_TABLE);
03123             /* This command never recurses */
03124             ATPrepAddInherit(rel);
03125             pass = AT_PASS_MISC;
03126             break;
03127         case AT_ValidateConstraint:     /* VALIDATE CONSTRAINT */
03128             ATSimplePermissions(rel, ATT_TABLE);
03129             /* Recursion occurs during execution phase */
03130             /* No command-specific prep needed except saving recurse flag */
03131             if (recurse)
03132                 cmd->subtype = AT_ValidateConstraintRecurse;
03133             pass = AT_PASS_MISC;
03134             break;
03135         case AT_EnableTrig:     /* ENABLE TRIGGER variants */
03136         case AT_EnableAlwaysTrig:
03137         case AT_EnableReplicaTrig:
03138         case AT_EnableTrigAll:
03139         case AT_EnableTrigUser:
03140         case AT_DisableTrig:    /* DISABLE TRIGGER variants */
03141         case AT_DisableTrigAll:
03142         case AT_DisableTrigUser:
03143         case AT_EnableRule:     /* ENABLE/DISABLE RULE variants */
03144         case AT_EnableAlwaysRule:
03145         case AT_EnableReplicaRule:
03146         case AT_DisableRule:
03147         case AT_DropInherit:    /* NO INHERIT */
03148         case AT_AddOf:          /* OF */
03149         case AT_DropOf: /* NOT OF */
03150             ATSimplePermissions(rel, ATT_TABLE);
03151             /* These commands never recurse */
03152             /* No command-specific prep needed */
03153             pass = AT_PASS_MISC;
03154             break;
03155         case AT_GenericOptions:
03156             ATSimplePermissions(rel, ATT_FOREIGN_TABLE);
03157             /* No command-specific prep needed */
03158             pass = AT_PASS_MISC;
03159             break;
03160         default:                /* oops */
03161             elog(ERROR, "unrecognized alter table type: %d",
03162                  (int) cmd->subtype);
03163             pass = 0;           /* keep compiler quiet */
03164             break;
03165     }
03166 
03167     /* Add the subcommand to the appropriate list for phase 2 */
03168     tab->subcmds[pass] = lappend(tab->subcmds[pass], cmd);
03169 }
03170 
03171 /*
03172  * ATRewriteCatalogs
03173  *
03174  * Traffic cop for ALTER TABLE Phase 2 operations.  Subcommands are
03175  * dispatched in a "safe" execution order (designed to avoid unnecessary
03176  * conflicts).
03177  */
03178 static void
03179 ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode)
03180 {
03181     int         pass;
03182     ListCell   *ltab;
03183 
03184     /*
03185      * We process all the tables "in parallel", one pass at a time.  This is
03186      * needed because we may have to propagate work from one table to another
03187      * (specifically, ALTER TYPE on a foreign key's PK has to dispatch the
03188      * re-adding of the foreign key constraint to the other table).  Work can
03189      * only be propagated into later passes, however.
03190      */
03191     for (pass = 0; pass < AT_NUM_PASSES; pass++)
03192     {
03193         /* Go through each table that needs to be processed */
03194         foreach(ltab, *wqueue)
03195         {
03196             AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
03197             List       *subcmds = tab->subcmds[pass];
03198             Relation    rel;
03199             ListCell   *lcmd;
03200 
03201             if (subcmds == NIL)
03202                 continue;
03203 
03204             /*
03205              * Appropriate lock was obtained by phase 1, needn't get it again
03206              */
03207             rel = relation_open(tab->relid, NoLock);
03208 
03209             foreach(lcmd, subcmds)
03210                 ATExecCmd(wqueue, tab, rel, (AlterTableCmd *) lfirst(lcmd), lockmode);
03211 
03212             /*
03213              * After the ALTER TYPE pass, do cleanup work (this is not done in
03214              * ATExecAlterColumnType since it should be done only once if
03215              * multiple columns of a table are altered).
03216              */
03217             if (pass == AT_PASS_ALTER_TYPE)
03218                 ATPostAlterTypeCleanup(wqueue, tab, lockmode);
03219 
03220             relation_close(rel, NoLock);
03221         }
03222     }
03223 
03224     /* Check to see if a toast table must be added. */
03225     foreach(ltab, *wqueue)
03226     {
03227         AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
03228 
03229         if (tab->relkind == RELKIND_RELATION ||
03230             tab->relkind == RELKIND_MATVIEW)
03231             AlterTableCreateToastTable(tab->relid, (Datum) 0);
03232     }
03233 }
03234 
03235 /*
03236  * ATExecCmd: dispatch a subcommand to appropriate execution routine
03237  */
03238 static void
03239 ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
03240           AlterTableCmd *cmd, LOCKMODE lockmode)
03241 {
03242     switch (cmd->subtype)
03243     {
03244         case AT_AddColumn:      /* ADD COLUMN */
03245         case AT_AddColumnToView:        /* add column via CREATE OR REPLACE
03246                                          * VIEW */
03247             ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
03248                             false, false, false, lockmode);
03249             break;
03250         case AT_AddColumnRecurse:
03251             ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
03252                             false, true, false, lockmode);
03253             break;
03254         case AT_ColumnDefault:  /* ALTER COLUMN DEFAULT */
03255             ATExecColumnDefault(rel, cmd->name, cmd->def, lockmode);
03256             break;
03257         case AT_DropNotNull:    /* ALTER COLUMN DROP NOT NULL */
03258             ATExecDropNotNull(rel, cmd->name, lockmode);
03259             break;
03260         case AT_SetNotNull:     /* ALTER COLUMN SET NOT NULL */
03261             ATExecSetNotNull(tab, rel, cmd->name, lockmode);
03262             break;
03263         case AT_SetStatistics:  /* ALTER COLUMN SET STATISTICS */
03264             ATExecSetStatistics(rel, cmd->name, cmd->def, lockmode);
03265             break;
03266         case AT_SetOptions:     /* ALTER COLUMN SET ( options ) */
03267             ATExecSetOptions(rel, cmd->name, cmd->def, false, lockmode);
03268             break;
03269         case AT_ResetOptions:   /* ALTER COLUMN RESET ( options ) */
03270             ATExecSetOptions(rel, cmd->name, cmd->def, true, lockmode);
03271             break;
03272         case AT_SetStorage:     /* ALTER COLUMN SET STORAGE */
03273             ATExecSetStorage(rel, cmd->name, cmd->def, lockmode);
03274             break;
03275         case AT_DropColumn:     /* DROP COLUMN */
03276             ATExecDropColumn(wqueue, rel, cmd->name,
03277                      cmd->behavior, false, false, cmd->missing_ok, lockmode);
03278             break;
03279         case AT_DropColumnRecurse:      /* DROP COLUMN with recursion */
03280             ATExecDropColumn(wqueue, rel, cmd->name,
03281                       cmd->behavior, true, false, cmd->missing_ok, lockmode);
03282             break;
03283         case AT_AddIndex:       /* ADD INDEX */
03284             ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, false, lockmode);
03285             break;
03286         case AT_ReAddIndex:     /* ADD INDEX */
03287             ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, true, lockmode);
03288             break;
03289         case AT_AddConstraint:  /* ADD CONSTRAINT */
03290             ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
03291                                 false, false, lockmode);
03292             break;
03293         case AT_AddConstraintRecurse:   /* ADD CONSTRAINT with recursion */
03294             ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
03295                                 true, false, lockmode);
03296             break;
03297         case AT_ReAddConstraint:    /* Re-add pre-existing check constraint */
03298             ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
03299                                 false, true, lockmode);
03300             break;
03301         case AT_AddIndexConstraint:     /* ADD CONSTRAINT USING INDEX */
03302             ATExecAddIndexConstraint(tab, rel, (IndexStmt *) cmd->def, lockmode);
03303             break;
03304         case AT_ValidateConstraint:     /* VALIDATE CONSTRAINT */
03305             ATExecValidateConstraint(rel, cmd->name, false, false, lockmode);
03306             break;
03307         case AT_ValidateConstraintRecurse:      /* VALIDATE CONSTRAINT with
03308                                                  * recursion */
03309             ATExecValidateConstraint(rel, cmd->name, true, false, lockmode);
03310             break;
03311         case AT_DropConstraint: /* DROP CONSTRAINT */
03312             ATExecDropConstraint(rel, cmd->name, cmd->behavior,
03313                                  false, false,
03314                                  cmd->missing_ok, lockmode);
03315             break;
03316         case AT_DropConstraintRecurse:  /* DROP CONSTRAINT with recursion */
03317             ATExecDropConstraint(rel, cmd->name, cmd->behavior,
03318                                  true, false,
03319                                  cmd->missing_ok, lockmode);
03320             break;
03321         case AT_AlterColumnType:        /* ALTER COLUMN TYPE */
03322             ATExecAlterColumnType(tab, rel, cmd, lockmode);
03323             break;
03324         case AT_AlterColumnGenericOptions:      /* ALTER COLUMN OPTIONS */
03325             ATExecAlterColumnGenericOptions(rel, cmd->name, (List *) cmd->def, lockmode);
03326             break;
03327         case AT_ChangeOwner:    /* ALTER OWNER */
03328             ATExecChangeOwner(RelationGetRelid(rel),
03329                               get_role_oid(cmd->name, false),
03330                               false, lockmode);
03331             break;
03332         case AT_ClusterOn:      /* CLUSTER ON */
03333             ATExecClusterOn(rel, cmd->name, lockmode);
03334             break;
03335         case AT_DropCluster:    /* SET WITHOUT CLUSTER */
03336             ATExecDropCluster(rel, lockmode);
03337             break;
03338         case AT_AddOids:        /* SET WITH OIDS */
03339             /* Use the ADD COLUMN code, unless prep decided to do nothing */
03340             if (cmd->def != NULL)
03341                 ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
03342                                 true, false, false, lockmode);
03343             break;
03344         case AT_AddOidsRecurse: /* SET WITH OIDS */
03345             /* Use the ADD COLUMN code, unless prep decided to do nothing */
03346             if (cmd->def != NULL)
03347                 ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
03348                                 true, true, false, lockmode);
03349             break;
03350         case AT_DropOids:       /* SET WITHOUT OIDS */
03351 
03352             /*
03353              * Nothing to do here; we'll have generated a DropColumn
03354              * subcommand to do the real work
03355              */
03356             break;
03357         case AT_SetTableSpace:  /* SET TABLESPACE */
03358 
03359             /*
03360              * Nothing to do here; Phase 3 does the work
03361              */
03362             break;
03363         case AT_SetRelOptions:  /* SET (...) */
03364         case AT_ResetRelOptions:        /* RESET (...) */
03365         case AT_ReplaceRelOptions:      /* replace entire option list */
03366             ATExecSetRelOptions(rel, (List *) cmd->def, cmd->subtype, lockmode);
03367             break;
03368         case AT_EnableTrig:     /* ENABLE TRIGGER name */
03369             ATExecEnableDisableTrigger(rel, cmd->name,
03370                                    TRIGGER_FIRES_ON_ORIGIN, false, lockmode);
03371             break;
03372         case AT_EnableAlwaysTrig:       /* ENABLE ALWAYS TRIGGER name */
03373             ATExecEnableDisableTrigger(rel, cmd->name,
03374                                        TRIGGER_FIRES_ALWAYS, false, lockmode);
03375             break;
03376         case AT_EnableReplicaTrig:      /* ENABLE REPLICA TRIGGER name */
03377             ATExecEnableDisableTrigger(rel, cmd->name,
03378                                   TRIGGER_FIRES_ON_REPLICA, false, lockmode);
03379             break;
03380         case AT_DisableTrig:    /* DISABLE TRIGGER name */
03381             ATExecEnableDisableTrigger(rel, cmd->name,
03382                                        TRIGGER_DISABLED, false, lockmode);
03383             break;
03384         case AT_EnableTrigAll:  /* ENABLE TRIGGER ALL */
03385             ATExecEnableDisableTrigger(rel, NULL,
03386                                    TRIGGER_FIRES_ON_ORIGIN, false, lockmode);
03387             break;
03388         case AT_DisableTrigAll: /* DISABLE TRIGGER ALL */
03389             ATExecEnableDisableTrigger(rel, NULL,
03390                                        TRIGGER_DISABLED, false, lockmode);
03391             break;
03392         case AT_EnableTrigUser: /* ENABLE TRIGGER USER */
03393             ATExecEnableDisableTrigger(rel, NULL,
03394                                     TRIGGER_FIRES_ON_ORIGIN, true, lockmode);
03395             break;
03396         case AT_DisableTrigUser:        /* DISABLE TRIGGER USER */
03397             ATExecEnableDisableTrigger(rel, NULL,
03398                                        TRIGGER_DISABLED, true, lockmode);
03399             break;
03400 
03401         case AT_EnableRule:     /* ENABLE RULE name */
03402             ATExecEnableDisableRule(rel, cmd->name,
03403                                     RULE_FIRES_ON_ORIGIN, lockmode);
03404             break;
03405         case AT_EnableAlwaysRule:       /* ENABLE ALWAYS RULE name */
03406             ATExecEnableDisableRule(rel, cmd->name,
03407                                     RULE_FIRES_ALWAYS, lockmode);
03408             break;
03409         case AT_EnableReplicaRule:      /* ENABLE REPLICA RULE name */
03410             ATExecEnableDisableRule(rel, cmd->name,
03411                                     RULE_FIRES_ON_REPLICA, lockmode);
03412             break;
03413         case AT_DisableRule:    /* DISABLE RULE name */
03414             ATExecEnableDisableRule(rel, cmd->name,
03415                                     RULE_DISABLED, lockmode);
03416             break;
03417 
03418         case AT_AddInherit:
03419             ATExecAddInherit(rel, (RangeVar *) cmd->def, lockmode);
03420             break;
03421         case AT_DropInherit:
03422             ATExecDropInherit(rel, (RangeVar *) cmd->def, lockmode);
03423             break;
03424         case AT_AddOf:
03425             ATExecAddOf(rel, (TypeName *) cmd->def, lockmode);
03426             break;
03427         case AT_DropOf:
03428             ATExecDropOf(rel, lockmode);
03429             break;
03430         case AT_GenericOptions:
03431             ATExecGenericOptions(rel, (List *) cmd->def);
03432             break;
03433         default:                /* oops */
03434             elog(ERROR, "unrecognized alter table type: %d",
03435                  (int) cmd->subtype);
03436             break;
03437     }
03438 
03439     /*
03440      * Bump the command counter to ensure the next subcommand in the sequence
03441      * can see the changes so far
03442      */
03443     CommandCounterIncrement();
03444 }
03445 
03446 /*
03447  * ATRewriteTables: ALTER TABLE phase 3
03448  */
03449 static void
03450 ATRewriteTables(List **wqueue, LOCKMODE lockmode)
03451 {
03452     ListCell   *ltab;
03453 
03454     /* Go through each table that needs to be checked or rewritten */
03455     foreach(ltab, *wqueue)
03456     {
03457         AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
03458 
03459         /* Foreign tables have no storage. */
03460         if (tab->relkind == RELKIND_FOREIGN_TABLE)
03461             continue;
03462 
03463         /*
03464          * If we change column data types or add/remove OIDs, the operation
03465          * has to be propagated to tables that use this table's rowtype as a
03466          * column type.  tab->newvals will also be non-NULL in the case where
03467          * we're adding a column with a default.  We choose to forbid that
03468          * case as well, since composite types might eventually support
03469          * defaults.
03470          *
03471          * (Eventually we'll probably need to check for composite type
03472          * dependencies even when we're just scanning the table without a
03473          * rewrite, but at the moment a composite type does not enforce any
03474          * constraints, so it's not necessary/appropriate to enforce them just
03475          * during ALTER.)
03476          */
03477         if (tab->newvals != NIL || tab->rewrite)
03478         {
03479             Relation    rel;
03480 
03481             rel = heap_open(tab->relid, NoLock);
03482             find_composite_type_dependencies(rel->rd_rel->reltype, rel, NULL);
03483             heap_close(rel, NoLock);
03484         }
03485 
03486         /*
03487          * We only need to rewrite the table if at least one column needs to
03488          * be recomputed, or we are adding/removing the OID column.
03489          */
03490         if (tab->rewrite)
03491         {
03492             /* Build a temporary relation and copy data */
03493             Relation    OldHeap;
03494             Oid         OIDNewHeap;
03495             Oid         NewTableSpace;
03496 
03497             OldHeap = heap_open(tab->relid, NoLock);
03498 
03499             /*
03500              * We don't support rewriting of system catalogs; there are too
03501              * many corner cases and too little benefit.  In particular this
03502              * is certainly not going to work for mapped catalogs.
03503              */
03504             if (IsSystemRelation(OldHeap))
03505                 ereport(ERROR,
03506                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03507                          errmsg("cannot rewrite system relation \"%s\"",
03508                                 RelationGetRelationName(OldHeap))));
03509 
03510             /*
03511              * Don't allow rewrite on temp tables of other backends ... their
03512              * local buffer manager is not going to cope.
03513              */
03514             if (RELATION_IS_OTHER_TEMP(OldHeap))
03515                 ereport(ERROR,
03516                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
03517                 errmsg("cannot rewrite temporary tables of other sessions")));
03518 
03519             /*
03520              * Select destination tablespace (same as original unless user
03521              * requested a change)
03522              */
03523             if (tab->newTableSpace)
03524                 NewTableSpace = tab->newTableSpace;
03525             else
03526                 NewTableSpace = OldHeap->rd_rel->reltablespace;
03527 
03528             heap_close(OldHeap, NoLock);
03529 
03530             /* Create transient table that will receive the modified data */
03531             OIDNewHeap = make_new_heap(tab->relid, NewTableSpace);
03532 
03533             /*
03534              * Copy the heap data into the new table with the desired
03535              * modifications, and test the current data within the table
03536              * against new constraints generated by ALTER TABLE commands.
03537              */
03538             ATRewriteTable(tab, OIDNewHeap, lockmode);
03539 
03540             /*
03541              * Swap the physical files of the old and new heaps, then rebuild
03542              * indexes and discard the old heap.  We can use RecentXmin for
03543              * the table's new relfrozenxid because we rewrote all the tuples
03544              * in ATRewriteTable, so no older Xid remains in the table.  Also,
03545              * we never try to swap toast tables by content, since we have no
03546              * interest in letting this code work on system catalogs.
03547              */
03548             finish_heap_swap(tab->relid, OIDNewHeap,
03549                              false, false, true,
03550                              !OidIsValid(tab->newTableSpace),
03551                              RecentXmin,
03552                              ReadNextMultiXactId());
03553         }
03554         else
03555         {
03556             /*
03557              * Test the current data within the table against new constraints
03558              * generated by ALTER TABLE commands, but don't rebuild data.
03559              */
03560             if (tab->constraints != NIL || tab->new_notnull)
03561                 ATRewriteTable(tab, InvalidOid, lockmode);
03562 
03563             /*
03564              * If we had SET TABLESPACE but no reason to reconstruct tuples,
03565              * just do a block-by-block copy.
03566              */
03567             if (tab->newTableSpace)
03568                 ATExecSetTableSpace(tab->relid, tab->newTableSpace, lockmode);
03569         }
03570     }
03571 
03572     /*
03573      * Foreign key constraints are checked in a final pass, since (a) it's
03574      * generally best to examine each one separately, and (b) it's at least
03575      * theoretically possible that we have changed both relations of the
03576      * foreign key, and we'd better have finished both rewrites before we try
03577      * to read the tables.
03578      */
03579     foreach(ltab, *wqueue)
03580     {
03581         AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
03582         Relation    rel = NULL;
03583         ListCell   *lcon;
03584 
03585         foreach(lcon, tab->constraints)
03586         {
03587             NewConstraint *con = lfirst(lcon);
03588 
03589             if (con->contype == CONSTR_FOREIGN)
03590             {
03591                 Constraint *fkconstraint = (Constraint *) con->qual;
03592                 Relation    refrel;
03593 
03594                 if (rel == NULL)
03595                 {
03596                     /* Long since locked, no need for another */
03597                     rel = heap_open(tab->relid, NoLock);
03598                 }
03599 
03600                 refrel = heap_open(con->refrelid, RowShareLock);
03601 
03602                 validateForeignKeyConstraint(fkconstraint->conname, rel, refrel,
03603                                              con->refindid,
03604                                              con->conid);
03605 
03606                 /*
03607                  * No need to mark the constraint row as validated, we did
03608                  * that when we inserted the row earlier.
03609                  */
03610 
03611                 heap_close(refrel, NoLock);
03612             }
03613         }
03614 
03615         if (rel)
03616             heap_close(rel, NoLock);
03617     }
03618 }
03619 
03620 /*
03621  * ATRewriteTable: scan or rewrite one table
03622  *
03623  * OIDNewHeap is InvalidOid if we don't need to rewrite
03624  */
03625 static void
03626 ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
03627 {
03628     Relation    oldrel;
03629     Relation    newrel;
03630     TupleDesc   oldTupDesc;
03631     TupleDesc   newTupDesc;
03632     bool        needscan = false;
03633     List       *notnull_attrs;
03634     int         i;
03635     ListCell   *l;
03636     EState     *estate;
03637     CommandId   mycid;
03638     BulkInsertState bistate;
03639     int         hi_options;
03640 
03641     /*
03642      * Open the relation(s).  We have surely already locked the existing
03643      * table.
03644      */
03645     oldrel = heap_open(tab->relid, NoLock);
03646     oldTupDesc = tab->oldDesc;
03647     newTupDesc = RelationGetDescr(oldrel);      /* includes all mods */
03648 
03649     if (OidIsValid(OIDNewHeap))
03650         newrel = heap_open(OIDNewHeap, lockmode);
03651     else
03652         newrel = NULL;
03653 
03654     /*
03655      * Prepare a BulkInsertState and options for heap_insert. Because we're
03656      * building a new heap, we can skip WAL-logging and fsync it to disk at
03657      * the end instead (unless WAL-logging is required for archiving or
03658      * streaming replication). The FSM is empty too, so don't bother using it.
03659      */
03660     if (newrel)
03661     {
03662         mycid = GetCurrentCommandId(true);
03663         bistate = GetBulkInsertState();
03664 
03665         hi_options = HEAP_INSERT_SKIP_FSM;
03666         if (!XLogIsNeeded())
03667             hi_options |= HEAP_INSERT_SKIP_WAL;
03668     }
03669     else
03670     {
03671         /* keep compiler quiet about using these uninitialized */
03672         mycid = 0;
03673         bistate = NULL;
03674         hi_options = 0;
03675     }
03676 
03677     /*
03678      * Generate the constraint and default execution states
03679      */
03680 
03681     estate = CreateExecutorState();
03682 
03683     /* Build the needed expression execution states */
03684     foreach(l, tab->constraints)
03685     {
03686         NewConstraint *con = lfirst(l);
03687 
03688         switch (con->contype)
03689         {
03690             case CONSTR_CHECK:
03691                 needscan = true;
03692                 con->qualstate = (List *)
03693                     ExecPrepareExpr((Expr *) con->qual, estate);
03694                 break;
03695             case CONSTR_FOREIGN:
03696                 /* Nothing to do here */
03697                 break;
03698             default:
03699                 elog(ERROR, "unrecognized constraint type: %d",
03700                      (int) con->contype);
03701         }
03702     }
03703 
03704     foreach(l, tab->newvals)
03705     {
03706         NewColumnValue *ex = lfirst(l);
03707 
03708         /* expr already planned */
03709         ex->exprstate = ExecInitExpr((Expr *) ex->expr, NULL);
03710     }
03711 
03712     notnull_attrs = NIL;
03713     if (newrel || tab->new_notnull)
03714     {
03715         /*
03716          * If we are rebuilding the tuples OR if we added any new NOT NULL
03717          * constraints, check all not-null constraints.  This is a bit of
03718          * overkill but it minimizes risk of bugs, and heap_attisnull is a
03719          * pretty cheap test anyway.
03720          */
03721         for (i = 0; i < newTupDesc->natts; i++)
03722         {
03723             if (newTupDesc->attrs[i]->attnotnull &&
03724                 !newTupDesc->attrs[i]->attisdropped)
03725                 notnull_attrs = lappend_int(notnull_attrs, i);
03726         }
03727         if (notnull_attrs)
03728             needscan = true;
03729     }
03730 
03731     if (newrel || needscan)
03732     {
03733         ExprContext *econtext;
03734         Datum      *values;
03735         bool       *isnull;
03736         TupleTableSlot *oldslot;
03737         TupleTableSlot *newslot;
03738         HeapScanDesc scan;
03739         HeapTuple   tuple;
03740         MemoryContext oldCxt;
03741         List       *dropped_attrs = NIL;
03742         ListCell   *lc;
03743 
03744         if (newrel)
03745             ereport(DEBUG1,
03746                     (errmsg("rewriting table \"%s\"",
03747                             RelationGetRelationName(oldrel))));
03748         else
03749             ereport(DEBUG1,
03750                     (errmsg("verifying table \"%s\"",
03751                             RelationGetRelationName(oldrel))));
03752 
03753         if (newrel)
03754         {
03755             /*
03756              * All predicate locks on the tuples or pages are about to be made
03757              * invalid, because we move tuples around.  Promote them to
03758              * relation locks.
03759              */
03760             TransferPredicateLocksToHeapRelation(oldrel);
03761         }
03762 
03763         econtext = GetPerTupleExprContext(estate);
03764 
03765         /*
03766          * Make tuple slots for old and new tuples.  Note that even when the
03767          * tuples are the same, the tupDescs might not be (consider ADD COLUMN
03768          * without a default).
03769          */
03770         oldslot = MakeSingleTupleTableSlot(oldTupDesc);
03771         newslot = MakeSingleTupleTableSlot(newTupDesc);
03772 
03773         /* Preallocate values/isnull arrays */
03774         i = Max(newTupDesc->natts, oldTupDesc->natts);
03775         values = (Datum *) palloc(i * sizeof(Datum));
03776         isnull = (bool *) palloc(i * sizeof(bool));
03777         memset(values, 0, i * sizeof(Datum));
03778         memset(isnull, true, i * sizeof(bool));
03779 
03780         /*
03781          * Any attributes that are dropped according to the new tuple
03782          * descriptor can be set to NULL. We precompute the list of dropped
03783          * attributes to avoid needing to do so in the per-tuple loop.
03784          */
03785         for (i = 0; i < newTupDesc->natts; i++)
03786         {
03787             if (newTupDesc->attrs[i]->attisdropped)
03788                 dropped_attrs = lappend_int(dropped_attrs, i);
03789         }
03790 
03791         /*
03792          * Scan through the rows, generating a new row if needed and then
03793          * checking all the constraints.
03794          */
03795         scan = heap_beginscan(oldrel, SnapshotNow, 0, NULL);
03796 
03797         /*
03798          * Switch to per-tuple memory context and reset it for each tuple
03799          * produced, so we don't leak memory.
03800          */
03801         oldCxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
03802 
03803         while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
03804         {
03805             if (tab->rewrite)
03806             {
03807                 Oid         tupOid = InvalidOid;
03808 
03809                 /* Extract data from old tuple */
03810                 heap_deform_tuple(tuple, oldTupDesc, values, isnull);
03811                 if (oldTupDesc->tdhasoid)
03812                     tupOid = HeapTupleGetOid(tuple);
03813 
03814                 /* Set dropped attributes to null in new tuple */
03815                 foreach(lc, dropped_attrs)
03816                     isnull[lfirst_int(lc)] = true;
03817 
03818                 /*
03819                  * Process supplied expressions to replace selected columns.
03820                  * Expression inputs come from the old tuple.
03821                  */
03822                 ExecStoreTuple(tuple, oldslot, InvalidBuffer, false);
03823                 econtext->ecxt_scantuple = oldslot;
03824 
03825                 foreach(l, tab->newvals)
03826                 {
03827                     NewColumnValue *ex = lfirst(l);
03828 
03829                     values[ex->attnum - 1] = ExecEvalExpr(ex->exprstate,
03830                                                           econtext,
03831                                                      &isnull[ex->attnum - 1],
03832                                                           NULL);
03833                 }
03834 
03835                 /*
03836                  * Form the new tuple. Note that we don't explicitly pfree it,
03837                  * since the per-tuple memory context will be reset shortly.
03838                  */
03839                 tuple = heap_form_tuple(newTupDesc, values, isnull);
03840 
03841                 /* Preserve OID, if any */
03842                 if (newTupDesc->tdhasoid)
03843                     HeapTupleSetOid(tuple, tupOid);
03844             }
03845 
03846             /* Now check any constraints on the possibly-changed tuple */
03847             ExecStoreTuple(tuple, newslot, InvalidBuffer, false);
03848             econtext->ecxt_scantuple = newslot;
03849 
03850             foreach(l, notnull_attrs)
03851             {
03852                 int         attn = lfirst_int(l);
03853 
03854                 if (heap_attisnull(tuple, attn + 1))
03855                     ereport(ERROR,
03856                             (errcode(ERRCODE_NOT_NULL_VIOLATION),
03857                              errmsg("column \"%s\" contains null values",
03858                                 NameStr(newTupDesc->attrs[attn]->attname)),
03859                              errtablecol(oldrel, attn + 1)));
03860             }
03861 
03862             foreach(l, tab->constraints)
03863             {
03864                 NewConstraint *con = lfirst(l);
03865 
03866                 switch (con->contype)
03867                 {
03868                     case CONSTR_CHECK:
03869                         if (!ExecQual(con->qualstate, econtext, true))
03870                             ereport(ERROR,
03871                                     (errcode(ERRCODE_CHECK_VIOLATION),
03872                                      errmsg("check constraint \"%s\" is violated by some row",
03873                                             con->name),
03874                                      errtableconstraint(oldrel, con->name)));
03875                         break;
03876                     case CONSTR_FOREIGN:
03877                         /* Nothing to do here */
03878                         break;
03879                     default:
03880                         elog(ERROR, "unrecognized constraint type: %d",
03881                              (int) con->contype);
03882                 }
03883             }
03884 
03885             /* Write the tuple out to the new relation */
03886             if (newrel)
03887                 heap_insert(newrel, tuple, mycid, hi_options, bistate);
03888 
03889             ResetExprContext(econtext);
03890 
03891             CHECK_FOR_INTERRUPTS();
03892         }
03893 
03894         MemoryContextSwitchTo(oldCxt);
03895         heap_endscan(scan);
03896 
03897         ExecDropSingleTupleTableSlot(oldslot);
03898         ExecDropSingleTupleTableSlot(newslot);
03899     }
03900 
03901     FreeExecutorState(estate);
03902 
03903     heap_close(oldrel, NoLock);
03904     if (newrel)
03905     {
03906         FreeBulkInsertState(bistate);
03907 
03908         /* If we skipped writing WAL, then we need to sync the heap. */
03909         if (hi_options & HEAP_INSERT_SKIP_WAL)
03910             heap_sync(newrel);
03911 
03912         heap_close(newrel, NoLock);
03913     }
03914 }
03915 
03916 /*
03917  * ATGetQueueEntry: find or create an entry in the ALTER TABLE work queue
03918  */
03919 static AlteredTableInfo *
03920 ATGetQueueEntry(List **wqueue, Relation rel)
03921 {
03922     Oid         relid = RelationGetRelid(rel);
03923     AlteredTableInfo *tab;
03924     ListCell   *ltab;
03925 
03926     foreach(ltab, *wqueue)
03927     {
03928         tab = (AlteredTableInfo *) lfirst(ltab);
03929         if (tab->relid == relid)
03930             return tab;
03931     }
03932 
03933     /*
03934      * Not there, so add it.  Note that we make a copy of the relation's
03935      * existing descriptor before anything interesting can happen to it.
03936      */
03937     tab = (AlteredTableInfo *) palloc0(sizeof(AlteredTableInfo));
03938     tab->relid = relid;
03939     tab->relkind = rel->rd_rel->relkind;
03940     tab->oldDesc = CreateTupleDescCopy(RelationGetDescr(rel));
03941 
03942     *wqueue = lappend(*wqueue, tab);
03943 
03944     return tab;
03945 }
03946 
03947 /*
03948  * ATSimplePermissions
03949  *
03950  * - Ensure that it is a relation (or possibly a view)
03951  * - Ensure this user is the owner
03952  * - Ensure that it is not a system table
03953  */
03954 static void
03955 ATSimplePermissions(Relation rel, int allowed_targets)
03956 {
03957     int         actual_target;
03958 
03959     switch (rel->rd_rel->relkind)
03960     {
03961         case RELKIND_RELATION:
03962             actual_target = ATT_TABLE;
03963             break;
03964         case RELKIND_VIEW:
03965             actual_target = ATT_VIEW;
03966             break;
03967         case RELKIND_MATVIEW:
03968             actual_target = ATT_MATVIEW;
03969             break;
03970         case RELKIND_INDEX:
03971             actual_target = ATT_INDEX;
03972             break;
03973         case RELKIND_COMPOSITE_TYPE:
03974             actual_target = ATT_COMPOSITE_TYPE;
03975             break;
03976         case RELKIND_FOREIGN_TABLE:
03977             actual_target = ATT_FOREIGN_TABLE;
03978             break;
03979         default:
03980             actual_target = 0;
03981             break;
03982     }
03983 
03984     /* Wrong target type? */
03985     if ((actual_target & allowed_targets) == 0)
03986         ATWrongRelkindError(rel, allowed_targets);
03987 
03988     /* Permissions checks */
03989     if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
03990         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
03991                        RelationGetRelationName(rel));
03992 
03993     if (!allowSystemTableMods && IsSystemRelation(rel))
03994         ereport(ERROR,
03995                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
03996                  errmsg("permission denied: \"%s\" is a system catalog",
03997                         RelationGetRelationName(rel))));
03998 }
03999 
04000 /*
04001  * ATWrongRelkindError
04002  *
04003  * Throw an error when a relation has been determined to be of the wrong
04004  * type.
04005  */
04006 static void
04007 ATWrongRelkindError(Relation rel, int allowed_targets)
04008 {
04009     char       *msg;
04010 
04011     switch (allowed_targets)
04012     {
04013         case ATT_TABLE:
04014             msg = _("\"%s\" is not a table");
04015             break;
04016         case ATT_TABLE | ATT_VIEW:
04017             msg = _("\"%s\" is not a table or view");
04018             break;
04019         case ATT_TABLE | ATT_VIEW | ATT_MATVIEW | ATT_INDEX:
04020             msg = _("\"%s\" is not a table, view, materialized view, or index");
04021             break;
04022         case ATT_TABLE | ATT_MATVIEW:
04023             msg = _("\"%s\" is not a table or materialized view");
04024             break;
04025         case ATT_TABLE | ATT_MATVIEW | ATT_INDEX:
04026             msg = _("\"%s\" is not a table, materialized view, or index");
04027             break;
04028         case ATT_TABLE | ATT_FOREIGN_TABLE:
04029             msg = _("\"%s\" is not a table or foreign table");
04030             break;
04031         case ATT_TABLE | ATT_COMPOSITE_TYPE | ATT_FOREIGN_TABLE:
04032             msg = _("\"%s\" is not a table, composite type, or foreign table");
04033             break;
04034         case ATT_TABLE | ATT_MATVIEW | ATT_INDEX | ATT_FOREIGN_TABLE:
04035             msg = _("\"%s\" is not a table, materialized view, composite type, or foreign table");
04036             break;
04037         case ATT_VIEW:
04038             msg = _("\"%s\" is not a view");
04039             break;
04040         case ATT_FOREIGN_TABLE:
04041             msg = _("\"%s\" is not a foreign table");
04042             break;
04043         default:
04044             /* shouldn't get here, add all necessary cases above */
04045             msg = _("\"%s\" is of the wrong type");
04046             break;
04047     }
04048 
04049     ereport(ERROR,
04050             (errcode(ERRCODE_WRONG_OBJECT_TYPE),
04051              errmsg(msg, RelationGetRelationName(rel))));
04052 }
04053 
04054 /*
04055  * ATSimpleRecursion
04056  *
04057  * Simple table recursion sufficient for most ALTER TABLE operations.
04058  * All direct and indirect children are processed in an unspecified order.
04059  * Note that if a child inherits from the original table via multiple
04060  * inheritance paths, it will be visited just once.
04061  */
04062 static void
04063 ATSimpleRecursion(List **wqueue, Relation rel,
04064                   AlterTableCmd *cmd, bool recurse, LOCKMODE lockmode)
04065 {
04066     /*
04067      * Propagate to children if desired.  Non-table relations never have
04068      * children, so no need to search in that case.
04069      */
04070     if (recurse && rel->rd_rel->relkind == RELKIND_RELATION)
04071     {
04072         Oid         relid = RelationGetRelid(rel);
04073         ListCell   *child;
04074         List       *children;
04075 
04076         children = find_all_inheritors(relid, lockmode, NULL);
04077 
04078         /*
04079          * find_all_inheritors does the recursive search of the inheritance
04080          * hierarchy, so all we have to do is process all of the relids in the
04081          * list that it returns.
04082          */
04083         foreach(child, children)
04084         {
04085             Oid         childrelid = lfirst_oid(child);
04086             Relation    childrel;
04087 
04088             if (childrelid == relid)
04089                 continue;
04090             /* find_all_inheritors already got lock */
04091             childrel = relation_open(childrelid, NoLock);
04092             CheckTableNotInUse(childrel, "ALTER TABLE");
04093             ATPrepCmd(wqueue, childrel, cmd, false, true, lockmode);
04094             relation_close(childrel, NoLock);
04095         }
04096     }
04097 }
04098 
04099 /*
04100  * ATTypedTableRecursion
04101  *
04102  * Propagate ALTER TYPE operations to the typed tables of that type.
04103  * Also check the RESTRICT/CASCADE behavior.  Given CASCADE, also permit
04104  * recursion to inheritance children of the typed tables.
04105  */
04106 static void
04107 ATTypedTableRecursion(List **wqueue, Relation rel, AlterTableCmd *cmd,
04108                       LOCKMODE lockmode)
04109 {
04110     ListCell   *child;
04111     List       *children;
04112 
04113     Assert(rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
04114 
04115     children = find_typed_table_dependencies(rel->rd_rel->reltype,
04116                                              RelationGetRelationName(rel),
04117                                              cmd->behavior);
04118 
04119     foreach(child, children)
04120     {
04121         Oid         childrelid = lfirst_oid(child);
04122         Relation    childrel;
04123 
04124         childrel = relation_open(childrelid, lockmode);
04125         CheckTableNotInUse(childrel, "ALTER TABLE");
04126         ATPrepCmd(wqueue, childrel, cmd, true, true, lockmode);
04127         relation_close(childrel, NoLock);
04128     }
04129 }
04130 
04131 
04132 /*
04133  * find_composite_type_dependencies
04134  *
04135  * Check to see if a composite type is being used as a column in some
04136  * other table (possibly nested several levels deep in composite types!).
04137  * Eventually, we'd like to propagate the check or rewrite operation
04138  * into other such tables, but for now, just error out if we find any.
04139  *
04140  * Caller should provide either a table name or a type name (not both) to
04141  * report in the error message, if any.
04142  *
04143  * We assume that functions and views depending on the type are not reasons
04144  * to reject the ALTER.  (How safe is this really?)
04145  */
04146 void
04147 find_composite_type_dependencies(Oid typeOid, Relation origRelation,
04148                                  const char *origTypeName)
04149 {
04150     Relation    depRel;
04151     ScanKeyData key[2];
04152     SysScanDesc depScan;
04153     HeapTuple   depTup;
04154     Oid         arrayOid;
04155 
04156     /*
04157      * We scan pg_depend to find those things that depend on the rowtype. (We
04158      * assume we can ignore refobjsubid for a rowtype.)
04159      */
04160     depRel = heap_open(DependRelationId, AccessShareLock);
04161 
04162     ScanKeyInit(&key[0],
04163                 Anum_pg_depend_refclassid,
04164                 BTEqualStrategyNumber, F_OIDEQ,
04165                 ObjectIdGetDatum(TypeRelationId));
04166     ScanKeyInit(&key[1],
04167                 Anum_pg_depend_refobjid,
04168                 BTEqualStrategyNumber, F_OIDEQ,
04169                 ObjectIdGetDatum(typeOid));
04170 
04171     depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
04172                                  SnapshotNow, 2, key);
04173 
04174     while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
04175     {
04176         Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
04177         Relation    rel;
04178         Form_pg_attribute att;
04179 
04180         /* Ignore dependees that aren't user columns of relations */
04181         /* (we assume system columns are never of rowtypes) */
04182         if (pg_depend->classid != RelationRelationId ||
04183             pg_depend->objsubid <= 0)
04184             continue;
04185 
04186         rel = relation_open(pg_depend->objid, AccessShareLock);
04187         att = rel->rd_att->attrs[pg_depend->objsubid - 1];
04188 
04189         if (rel->rd_rel->relkind == RELKIND_RELATION ||
04190             rel->rd_rel->relkind == RELKIND_MATVIEW)
04191         {
04192             if (origTypeName)
04193                 ereport(ERROR,
04194                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
04195                          errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
04196                                 origTypeName,
04197                                 RelationGetRelationName(rel),
04198                                 NameStr(att->attname))));
04199             else if (origRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
04200                 ereport(ERROR,
04201                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
04202                          errmsg("cannot alter type \"%s\" because column \"%s.%s\" uses it",
04203                                 RelationGetRelationName(origRelation),
04204                                 RelationGetRelationName(rel),
04205                                 NameStr(att->attname))));
04206             else if (origRelation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
04207                 ereport(ERROR,
04208                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
04209                          errmsg("cannot alter foreign table \"%s\" because column \"%s.%s\" uses its row type",
04210                                 RelationGetRelationName(origRelation),
04211                                 RelationGetRelationName(rel),
04212                                 NameStr(att->attname))));
04213             else
04214                 ereport(ERROR,
04215                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
04216                          errmsg("cannot alter table \"%s\" because column \"%s.%s\" uses its row type",
04217                                 RelationGetRelationName(origRelation),
04218                                 RelationGetRelationName(rel),
04219                                 NameStr(att->attname))));
04220         }
04221         else if (OidIsValid(rel->rd_rel->reltype))
04222         {
04223             /*
04224              * A view or composite type itself isn't a problem, but we must
04225              * recursively check for indirect dependencies via its rowtype.
04226              */
04227             find_composite_type_dependencies(rel->rd_rel->reltype,
04228                                              origRelation, origTypeName);
04229         }
04230 
04231         relation_close(rel, AccessShareLock);
04232     }
04233 
04234     systable_endscan(depScan);
04235 
04236     relation_close(depRel, AccessShareLock);
04237 
04238     /*
04239      * If there's an array type for the rowtype, must check for uses of it,
04240      * too.
04241      */
04242     arrayOid = get_array_type(typeOid);
04243     if (OidIsValid(arrayOid))
04244         find_composite_type_dependencies(arrayOid, origRelation, origTypeName);
04245 }
04246 
04247 
04248 /*
04249  * find_typed_table_dependencies
04250  *
04251  * Check to see if a composite type is being used as the type of a
04252  * typed table.  Abort if any are found and behavior is RESTRICT.
04253  * Else return the list of tables.
04254  */
04255 static List *
04256 find_typed_table_dependencies(Oid typeOid, const char *typeName, DropBehavior behavior)
04257 {
04258     Relation    classRel;
04259     ScanKeyData key[1];
04260     HeapScanDesc scan;
04261     HeapTuple   tuple;
04262     List       *result = NIL;
04263 
04264     classRel = heap_open(RelationRelationId, AccessShareLock);
04265 
04266     ScanKeyInit(&key[0],
04267                 Anum_pg_class_reloftype,
04268                 BTEqualStrategyNumber, F_OIDEQ,
04269                 ObjectIdGetDatum(typeOid));
04270 
04271     scan = heap_beginscan(classRel, SnapshotNow, 1, key);
04272 
04273     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
04274     {
04275         if (behavior == DROP_RESTRICT)
04276             ereport(ERROR,
04277                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
04278                      errmsg("cannot alter type \"%s\" because it is the type of a typed table",
04279                             typeName),
04280             errhint("Use ALTER ... CASCADE to alter the typed tables too.")));
04281         else
04282             result = lappend_oid(result, HeapTupleGetOid(tuple));
04283     }
04284 
04285     heap_endscan(scan);
04286     heap_close(classRel, AccessShareLock);
04287 
04288     return result;
04289 }
04290 
04291 
04292 /*
04293  * check_of_type
04294  *
04295  * Check whether a type is suitable for CREATE TABLE OF/ALTER TABLE OF.  If it
04296  * isn't suitable, throw an error.  Currently, we require that the type
04297  * originated with CREATE TYPE AS.  We could support any row type, but doing so
04298  * would require handling a number of extra corner cases in the DDL commands.
04299  */
04300 void
04301 check_of_type(HeapTuple typetuple)
04302 {
04303     Form_pg_type typ = (Form_pg_type) GETSTRUCT(typetuple);
04304     bool        typeOk = false;
04305 
04306     if (typ->typtype == TYPTYPE_COMPOSITE)
04307     {
04308         Relation    typeRelation;
04309 
04310         Assert(OidIsValid(typ->typrelid));
04311         typeRelation = relation_open(typ->typrelid, AccessShareLock);
04312         typeOk = (typeRelation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE);
04313 
04314         /*
04315          * Close the parent rel, but keep our AccessShareLock on it until xact
04316          * commit.  That will prevent someone else from deleting or ALTERing
04317          * the type before the typed table creation/conversion commits.
04318          */
04319         relation_close(typeRelation, NoLock);
04320     }
04321     if (!typeOk)
04322         ereport(ERROR,
04323                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
04324                  errmsg("type %s is not a composite type",
04325                         format_type_be(HeapTupleGetOid(typetuple)))));
04326 }
04327 
04328 
04329 /*
04330  * ALTER TABLE ADD COLUMN
04331  *
04332  * Adds an additional attribute to a relation making the assumption that
04333  * CHECK, NOT NULL, and FOREIGN KEY constraints will be removed from the
04334  * AT_AddColumn AlterTableCmd by parse_utilcmd.c and added as independent
04335  * AlterTableCmd's.
04336  *
04337  * ADD COLUMN cannot use the normal ALTER TABLE recursion mechanism, because we
04338  * have to decide at runtime whether to recurse or not depending on whether we
04339  * actually add a column or merely merge with an existing column.  (We can't
04340  * check this in a static pre-pass because it won't handle multiple inheritance
04341  * situations correctly.)
04342  */
04343 static void
04344 ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
04345                 AlterTableCmd *cmd, LOCKMODE lockmode)
04346 {
04347     if (rel->rd_rel->reloftype && !recursing)
04348         ereport(ERROR,
04349                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
04350                  errmsg("cannot add column to typed table")));
04351 
04352     if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
04353         ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
04354 
04355     if (recurse)
04356         cmd->subtype = AT_AddColumnRecurse;
04357 }
04358 
04359 static void
04360 ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
04361                 ColumnDef *colDef, bool isOid,
04362                 bool recurse, bool recursing, LOCKMODE lockmode)
04363 {
04364     Oid         myrelid = RelationGetRelid(rel);
04365     Relation    pgclass,
04366                 attrdesc;
04367     HeapTuple   reltup;
04368     FormData_pg_attribute attribute;
04369     int         newattnum;
04370     char        relkind;
04371     HeapTuple   typeTuple;
04372     Oid         typeOid;
04373     int32       typmod;
04374     Oid         collOid;
04375     Form_pg_type tform;
04376     Expr       *defval;
04377     List       *children;
04378     ListCell   *child;
04379     AclResult   aclresult;
04380 
04381     /* At top level, permission check was done in ATPrepCmd, else do it */
04382     if (recursing)
04383         ATSimplePermissions(rel, ATT_TABLE);
04384 
04385     attrdesc = heap_open(AttributeRelationId, RowExclusiveLock);
04386 
04387     /*
04388      * Are we adding the column to a recursion child?  If so, check whether to
04389      * merge with an existing definition for the column.  If we do merge, we
04390      * must not recurse.  Children will already have the column, and recursing
04391      * into them would mess up attinhcount.
04392      */
04393     if (colDef->inhcount > 0)
04394     {
04395         HeapTuple   tuple;
04396 
04397         /* Does child already have a column by this name? */
04398         tuple = SearchSysCacheCopyAttName(myrelid, colDef->colname);
04399         if (HeapTupleIsValid(tuple))
04400         {
04401             Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
04402             Oid         ctypeId;
04403             int32       ctypmod;
04404             Oid         ccollid;
04405 
04406             /* Child column must match on type, typmod, and collation */
04407             typenameTypeIdAndMod(NULL, colDef->typeName, &ctypeId, &ctypmod);
04408             if (ctypeId != childatt->atttypid ||
04409                 ctypmod != childatt->atttypmod)
04410                 ereport(ERROR,
04411                         (errcode(ERRCODE_DATATYPE_MISMATCH),
04412                          errmsg("child table \"%s\" has different type for column \"%s\"",
04413                             RelationGetRelationName(rel), colDef->colname)));
04414             ccollid = GetColumnDefCollation(NULL, colDef, ctypeId);
04415             if (ccollid != childatt->attcollation)
04416                 ereport(ERROR,
04417                         (errcode(ERRCODE_COLLATION_MISMATCH),
04418                          errmsg("child table \"%s\" has different collation for column \"%s\"",
04419                               RelationGetRelationName(rel), colDef->colname),
04420                          errdetail("\"%s\" versus \"%s\"",
04421                                    get_collation_name(ccollid),
04422                                get_collation_name(childatt->attcollation))));
04423 
04424             /* If it's OID, child column must actually be OID */
04425             if (isOid && childatt->attnum != ObjectIdAttributeNumber)
04426                 ereport(ERROR,
04427                         (errcode(ERRCODE_DATATYPE_MISMATCH),
04428                  errmsg("child table \"%s\" has a conflicting \"%s\" column",
04429                         RelationGetRelationName(rel), colDef->colname)));
04430 
04431             /* Bump the existing child att's inhcount */
04432             childatt->attinhcount++;
04433             simple_heap_update(attrdesc, &tuple->t_self, tuple);
04434             CatalogUpdateIndexes(attrdesc, tuple);
04435 
04436             heap_freetuple(tuple);
04437 
04438             /* Inform the user about the merge */
04439             ereport(NOTICE,
04440               (errmsg("merging definition of column \"%s\" for child \"%s\"",
04441                       colDef->colname, RelationGetRelationName(rel))));
04442 
04443             heap_close(attrdesc, RowExclusiveLock);
04444             return;
04445         }
04446     }
04447 
04448     pgclass = heap_open(RelationRelationId, RowExclusiveLock);
04449 
04450     reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
04451     if (!HeapTupleIsValid(reltup))
04452         elog(ERROR, "cache lookup failed for relation %u", myrelid);
04453     relkind = ((Form_pg_class) GETSTRUCT(reltup))->relkind;
04454 
04455     /* new name should not already exist */
04456     check_for_column_name_collision(rel, colDef->colname);
04457 
04458     /* Determine the new attribute's number */
04459     if (isOid)
04460         newattnum = ObjectIdAttributeNumber;
04461     else
04462     {
04463         newattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts + 1;
04464         if (newattnum > MaxHeapAttributeNumber)
04465             ereport(ERROR,
04466                     (errcode(ERRCODE_TOO_MANY_COLUMNS),
04467                      errmsg("tables can have at most %d columns",
04468                             MaxHeapAttributeNumber)));
04469     }
04470 
04471     typeTuple = typenameType(NULL, colDef->typeName, &typmod);
04472     tform = (Form_pg_type) GETSTRUCT(typeTuple);
04473     typeOid = HeapTupleGetOid(typeTuple);
04474 
04475     aclresult = pg_type_aclcheck(typeOid, GetUserId(), ACL_USAGE);
04476     if (aclresult != ACLCHECK_OK)
04477         aclcheck_error_type(aclresult, typeOid);
04478 
04479     collOid = GetColumnDefCollation(NULL, colDef, typeOid);
04480 
04481     /* make sure datatype is legal for a column */
04482     CheckAttributeType(colDef->colname, typeOid, collOid,
04483                        list_make1_oid(rel->rd_rel->reltype),
04484                        false);
04485 
04486     /* construct new attribute's pg_attribute entry */
04487     attribute.attrelid = myrelid;
04488     namestrcpy(&(attribute.attname), colDef->colname);
04489     attribute.atttypid = typeOid;
04490     attribute.attstattarget = (newattnum > 0) ? -1 : 0;
04491     attribute.attlen = tform->typlen;
04492     attribute.attcacheoff = -1;
04493     attribute.atttypmod = typmod;
04494     attribute.attnum = newattnum;
04495     attribute.attbyval = tform->typbyval;
04496     attribute.attndims = list_length(colDef->typeName->arrayBounds);
04497     attribute.attstorage = tform->typstorage;
04498     attribute.attalign = tform->typalign;
04499     attribute.attnotnull = colDef->is_not_null;
04500     attribute.atthasdef = false;
04501     attribute.attisdropped = false;
04502     attribute.attislocal = colDef->is_local;
04503     attribute.attinhcount = colDef->inhcount;
04504     attribute.attcollation = collOid;
04505     /* attribute.attacl is handled by InsertPgAttributeTuple */
04506 
04507     ReleaseSysCache(typeTuple);
04508 
04509     InsertPgAttributeTuple(attrdesc, &attribute, NULL);
04510 
04511     heap_close(attrdesc, RowExclusiveLock);
04512 
04513     /*
04514      * Update pg_class tuple as appropriate
04515      */
04516     if (isOid)
04517         ((Form_pg_class) GETSTRUCT(reltup))->relhasoids = true;
04518     else
04519         ((Form_pg_class) GETSTRUCT(reltup))->relnatts = newattnum;
04520 
04521     simple_heap_update(pgclass, &reltup->t_self, reltup);
04522 
04523     /* keep catalog indexes current */
04524     CatalogUpdateIndexes(pgclass, reltup);
04525 
04526     heap_freetuple(reltup);
04527 
04528     /* Post creation hook for new attribute */
04529     InvokeObjectPostCreateHook(RelationRelationId, myrelid, newattnum);
04530 
04531     heap_close(pgclass, RowExclusiveLock);
04532 
04533     /* Make the attribute's catalog entry visible */
04534     CommandCounterIncrement();
04535 
04536     /*
04537      * Store the DEFAULT, if any, in the catalogs
04538      */
04539     if (colDef->raw_default)
04540     {
04541         RawColumnDefault *rawEnt;
04542 
04543         rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
04544         rawEnt->attnum = attribute.attnum;
04545         rawEnt->raw_default = copyObject(colDef->raw_default);
04546 
04547         /*
04548          * This function is intended for CREATE TABLE, so it processes a
04549          * _list_ of defaults, but we just do one.
04550          */
04551         AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
04552                                   false, true, false);
04553 
04554         /* Make the additional catalog changes visible */
04555         CommandCounterIncrement();
04556     }
04557 
04558     /*
04559      * Tell Phase 3 to fill in the default expression, if there is one.
04560      *
04561      * If there is no default, Phase 3 doesn't have to do anything, because
04562      * that effectively means that the default is NULL.  The heap tuple access
04563      * routines always check for attnum > # of attributes in tuple, and return
04564      * NULL if so, so without any modification of the tuple data we will get
04565      * the effect of NULL values in the new column.
04566      *
04567      * An exception occurs when the new column is of a domain type: the domain
04568      * might have a NOT NULL constraint, or a check constraint that indirectly
04569      * rejects nulls.  If there are any domain constraints then we construct
04570      * an explicit NULL default value that will be passed through
04571      * CoerceToDomain processing.  (This is a tad inefficient, since it causes
04572      * rewriting the table which we really don't have to do, but the present
04573      * design of domain processing doesn't offer any simple way of checking
04574      * the constraints more directly.)
04575      *
04576      * Note: we use build_column_default, and not just the cooked default
04577      * returned by AddRelationNewConstraints, so that the right thing happens
04578      * when a datatype's default applies.
04579      *
04580      * We skip this step completely for views and foreign tables.  For a view,
04581      * we can only get here from CREATE OR REPLACE VIEW, which historically
04582      * doesn't set up defaults, not even for domain-typed columns.  And in any
04583      * case we mustn't invoke Phase 3 on a view or foreign table, since they
04584      * have no storage.
04585      */
04586     if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE
04587         && relkind != RELKIND_FOREIGN_TABLE && attribute.attnum > 0)
04588     {
04589         defval = (Expr *) build_column_default(rel, attribute.attnum);
04590 
04591         if (!defval && GetDomainConstraints(typeOid) != NIL)
04592         {
04593             Oid         baseTypeId;
04594             int32       baseTypeMod;
04595             Oid         baseTypeColl;
04596 
04597             baseTypeMod = typmod;
04598             baseTypeId = getBaseTypeAndTypmod(typeOid, &baseTypeMod);
04599             baseTypeColl = get_typcollation(baseTypeId);
04600             defval = (Expr *) makeNullConst(baseTypeId, baseTypeMod, baseTypeColl);
04601             defval = (Expr *) coerce_to_target_type(NULL,
04602                                                     (Node *) defval,
04603                                                     baseTypeId,
04604                                                     typeOid,
04605                                                     typmod,
04606                                                     COERCION_ASSIGNMENT,
04607                                                     COERCE_IMPLICIT_CAST,
04608                                                     -1);
04609             if (defval == NULL) /* should not happen */
04610                 elog(ERROR, "failed to coerce base type to domain");
04611         }
04612 
04613         if (defval)
04614         {
04615             NewColumnValue *newval;
04616 
04617             newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
04618             newval->attnum = attribute.attnum;
04619             newval->expr = expression_planner(defval);
04620 
04621             tab->newvals = lappend(tab->newvals, newval);
04622             tab->rewrite = true;
04623         }
04624 
04625         /*
04626          * If the new column is NOT NULL, tell Phase 3 it needs to test that.
04627          * (Note we don't do this for an OID column.  OID will be marked not
04628          * null, but since it's filled specially, there's no need to test
04629          * anything.)
04630          */
04631         tab->new_notnull |= colDef->is_not_null;
04632     }
04633 
04634     /*
04635      * If we are adding an OID column, we have to tell Phase 3 to rewrite the
04636      * table to fix that.
04637      */
04638     if (isOid)
04639         tab->rewrite = true;
04640 
04641     /*
04642      * Add needed dependency entries for the new column.
04643      */
04644     add_column_datatype_dependency(myrelid, newattnum, attribute.atttypid);
04645     add_column_collation_dependency(myrelid, newattnum, attribute.attcollation);
04646 
04647     /*
04648      * Propagate to children as appropriate.  Unlike most other ALTER
04649      * routines, we have to do this one level of recursion at a time; we can't
04650      * use find_all_inheritors to do it in one pass.
04651      */
04652     children = find_inheritance_children(RelationGetRelid(rel), lockmode);
04653 
04654     /*
04655      * If we are told not to recurse, there had better not be any child
04656      * tables; else the addition would put them out of step.
04657      */
04658     if (children && !recurse)
04659         ereport(ERROR,
04660                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
04661                  errmsg("column must be added to child tables too")));
04662 
04663     /* Children should see column as singly inherited */
04664     if (!recursing)
04665     {
04666         colDef = copyObject(colDef);
04667         colDef->inhcount = 1;
04668         colDef->is_local = false;
04669     }
04670 
04671     foreach(child, children)
04672     {
04673         Oid         childrelid = lfirst_oid(child);
04674         Relation    childrel;
04675         AlteredTableInfo *childtab;
04676 
04677         /* find_inheritance_children already got lock */
04678         childrel = heap_open(childrelid, NoLock);
04679         CheckTableNotInUse(childrel, "ALTER TABLE");
04680 
04681         /* Find or create work queue entry for this table */
04682         childtab = ATGetQueueEntry(wqueue, childrel);
04683 
04684         /* Recurse to child */
04685         ATExecAddColumn(wqueue, childtab, childrel,
04686                         colDef, isOid, recurse, true, lockmode);
04687 
04688         heap_close(childrel, NoLock);
04689     }
04690 }
04691 
04692 /*
04693  * If a new or renamed column will collide with the name of an existing
04694  * column, error out.
04695  */
04696 static void
04697 check_for_column_name_collision(Relation rel, const char *colname)
04698 {
04699     HeapTuple   attTuple;
04700     int         attnum;
04701 
04702     /*
04703      * this test is deliberately not attisdropped-aware, since if one tries to
04704      * add a column matching a dropped column name, it's gonna fail anyway.
04705      */
04706     attTuple = SearchSysCache2(ATTNAME,
04707                                ObjectIdGetDatum(RelationGetRelid(rel)),
04708                                PointerGetDatum(colname));
04709     if (!HeapTupleIsValid(attTuple))
04710         return;
04711 
04712     attnum = ((Form_pg_attribute) GETSTRUCT(attTuple))->attnum;
04713     ReleaseSysCache(attTuple);
04714 
04715     /*
04716      * We throw a different error message for conflicts with system column
04717      * names, since they are normally not shown and the user might otherwise
04718      * be confused about the reason for the conflict.
04719      */
04720     if (attnum <= 0)
04721         ereport(ERROR,
04722                 (errcode(ERRCODE_DUPLICATE_COLUMN),
04723              errmsg("column name \"%s\" conflicts with a system column name",
04724                     colname)));
04725     else
04726         ereport(ERROR,
04727                 (errcode(ERRCODE_DUPLICATE_COLUMN),
04728                  errmsg("column \"%s\" of relation \"%s\" already exists",
04729                         colname, RelationGetRelationName(rel))));
04730 }
04731 
04732 /*
04733  * Install a column's dependency on its datatype.
04734  */
04735 static void
04736 add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid)
04737 {
04738     ObjectAddress myself,
04739                 referenced;
04740 
04741     myself.classId = RelationRelationId;
04742     myself.objectId = relid;
04743     myself.objectSubId = attnum;
04744     referenced.classId = TypeRelationId;
04745     referenced.objectId = typid;
04746     referenced.objectSubId = 0;
04747     recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
04748 }
04749 
04750 /*
04751  * Install a column's dependency on its collation.
04752  */
04753 static void
04754 add_column_collation_dependency(Oid relid, int32 attnum, Oid collid)
04755 {
04756     ObjectAddress myself,
04757                 referenced;
04758 
04759     /* We know the default collation is pinned, so don't bother recording it */
04760     if (OidIsValid(collid) && collid != DEFAULT_COLLATION_OID)
04761     {
04762         myself.classId = RelationRelationId;
04763         myself.objectId = relid;
04764         myself.objectSubId = attnum;
04765         referenced.classId = CollationRelationId;
04766         referenced.objectId = collid;
04767         referenced.objectSubId = 0;
04768         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
04769     }
04770 }
04771 
04772 /*
04773  * ALTER TABLE SET WITH OIDS
04774  *
04775  * Basically this is an ADD COLUMN for the special OID column.  We have
04776  * to cons up a ColumnDef node because the ADD COLUMN code needs one.
04777  */
04778 static void
04779 ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOCKMODE lockmode)
04780 {
04781     /* If we're recursing to a child table, the ColumnDef is already set up */
04782     if (cmd->def == NULL)
04783     {
04784         ColumnDef  *cdef = makeNode(ColumnDef);
04785 
04786         cdef->colname = pstrdup("oid");
04787         cdef->typeName = makeTypeNameFromOid(OIDOID, -1);
04788         cdef->inhcount = 0;
04789         cdef->is_local = true;
04790         cdef->is_not_null = true;
04791         cdef->storage = 0;
04792         cmd->def = (Node *) cdef;
04793     }
04794     ATPrepAddColumn(wqueue, rel, recurse, false, cmd, lockmode);
04795 
04796     if (recurse)
04797         cmd->subtype = AT_AddOidsRecurse;
04798 }
04799 
04800 /*
04801  * ALTER TABLE ALTER COLUMN DROP NOT NULL
04802  */
04803 static void
04804 ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
04805 {
04806     HeapTuple   tuple;
04807     AttrNumber  attnum;
04808     Relation    attr_rel;
04809     List       *indexoidlist;
04810     ListCell   *indexoidscan;
04811 
04812     /*
04813      * lookup the attribute
04814      */
04815     attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
04816 
04817     tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
04818 
04819     if (!HeapTupleIsValid(tuple))
04820         ereport(ERROR,
04821                 (errcode(ERRCODE_UNDEFINED_COLUMN),
04822                  errmsg("column \"%s\" of relation \"%s\" does not exist",
04823                         colName, RelationGetRelationName(rel))));
04824 
04825     attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
04826 
04827     /* Prevent them from altering a system attribute */
04828     if (attnum <= 0)
04829         ereport(ERROR,
04830                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
04831                  errmsg("cannot alter system column \"%s\"",
04832                         colName)));
04833 
04834     /*
04835      * Check that the attribute is not in a primary key
04836      *
04837      * Note: we'll throw error even if the pkey index is not valid.
04838      */
04839 
04840     /* Loop over all indexes on the relation */
04841     indexoidlist = RelationGetIndexList(rel);
04842 
04843     foreach(indexoidscan, indexoidlist)
04844     {
04845         Oid         indexoid = lfirst_oid(indexoidscan);
04846         HeapTuple   indexTuple;
04847         Form_pg_index indexStruct;
04848         int         i;
04849 
04850         indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
04851         if (!HeapTupleIsValid(indexTuple))
04852             elog(ERROR, "cache lookup failed for index %u", indexoid);
04853         indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
04854 
04855         /* If the index is not a primary key, skip the check */
04856         if (indexStruct->indisprimary)
04857         {
04858             /*
04859              * Loop over each attribute in the primary key and see if it
04860              * matches the to-be-altered attribute
04861              */
04862             for (i = 0; i < indexStruct->indnatts; i++)
04863             {
04864                 if (indexStruct->indkey.values[i] == attnum)
04865                     ereport(ERROR,
04866                             (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
04867                              errmsg("column \"%s\" is in a primary key",
04868                                     colName)));
04869             }
04870         }
04871 
04872         ReleaseSysCache(indexTuple);
04873     }
04874 
04875     list_free(indexoidlist);
04876 
04877     /*
04878      * Okay, actually perform the catalog change ... if needed
04879      */
04880     if (((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull)
04881     {
04882         ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = FALSE;
04883 
04884         simple_heap_update(attr_rel, &tuple->t_self, tuple);
04885 
04886         /* keep the system catalog indexes current */
04887         CatalogUpdateIndexes(attr_rel, tuple);
04888     }
04889 
04890     InvokeObjectPostAlterHook(RelationRelationId,
04891                               RelationGetRelid(rel), attnum);
04892 
04893     heap_close(attr_rel, RowExclusiveLock);
04894 }
04895 
04896 /*
04897  * ALTER TABLE ALTER COLUMN SET NOT NULL
04898  */
04899 static void
04900 ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
04901                  const char *colName, LOCKMODE lockmode)
04902 {
04903     HeapTuple   tuple;
04904     AttrNumber  attnum;
04905     Relation    attr_rel;
04906 
04907     /*
04908      * lookup the attribute
04909      */
04910     attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
04911 
04912     tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
04913 
04914     if (!HeapTupleIsValid(tuple))
04915         ereport(ERROR,
04916                 (errcode(ERRCODE_UNDEFINED_COLUMN),
04917                  errmsg("column \"%s\" of relation \"%s\" does not exist",
04918                         colName, RelationGetRelationName(rel))));
04919 
04920     attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
04921 
04922     /* Prevent them from altering a system attribute */
04923     if (attnum <= 0)
04924         ereport(ERROR,
04925                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
04926                  errmsg("cannot alter system column \"%s\"",
04927                         colName)));
04928 
04929     /*
04930      * Okay, actually perform the catalog change ... if needed
04931      */
04932     if (!((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull)
04933     {
04934         ((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = TRUE;
04935 
04936         simple_heap_update(attr_rel, &tuple->t_self, tuple);
04937 
04938         /* keep the system catalog indexes current */
04939         CatalogUpdateIndexes(attr_rel, tuple);
04940 
04941         /* Tell Phase 3 it needs to test the constraint */
04942         tab->new_notnull = true;
04943     }
04944 
04945     InvokeObjectPostAlterHook(RelationRelationId,
04946                               RelationGetRelid(rel), attnum);
04947 
04948     heap_close(attr_rel, RowExclusiveLock);
04949 }
04950 
04951 /*
04952  * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT
04953  */
04954 static void
04955 ATExecColumnDefault(Relation rel, const char *colName,
04956                     Node *newDefault, LOCKMODE lockmode)
04957 {
04958     AttrNumber  attnum;
04959 
04960     /*
04961      * get the number of the attribute
04962      */
04963     attnum = get_attnum(RelationGetRelid(rel), colName);
04964     if (attnum == InvalidAttrNumber)
04965         ereport(ERROR,
04966                 (errcode(ERRCODE_UNDEFINED_COLUMN),
04967                  errmsg("column \"%s\" of relation \"%s\" does not exist",
04968                         colName, RelationGetRelationName(rel))));
04969 
04970     /* Prevent them from altering a system attribute */
04971     if (attnum <= 0)
04972         ereport(ERROR,
04973                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
04974                  errmsg("cannot alter system column \"%s\"",
04975                         colName)));
04976 
04977     /*
04978      * Remove any old default for the column.  We use RESTRICT here for
04979      * safety, but at present we do not expect anything to depend on the
04980      * default.
04981      *
04982      * We treat removing the existing default as an internal operation when it
04983      * is preparatory to adding a new default, but as a user-initiated
04984      * operation when the user asked for a drop.
04985      */
04986     RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, false,
04987                       newDefault == NULL ? false : true);
04988 
04989     if (newDefault)
04990     {
04991         /* SET DEFAULT */
04992         RawColumnDefault *rawEnt;
04993 
04994         rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
04995         rawEnt->attnum = attnum;
04996         rawEnt->raw_default = newDefault;
04997 
04998         /*
04999          * This function is intended for CREATE TABLE, so it processes a
05000          * _list_ of defaults, but we just do one.
05001          */
05002         AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
05003                                   false, true, false);
05004     }
05005 }
05006 
05007 /*
05008  * ALTER TABLE ALTER COLUMN SET STATISTICS
05009  */
05010 static void
05011 ATPrepSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
05012 {
05013     /*
05014      * We do our own permission checking because (a) we want to allow SET
05015      * STATISTICS on indexes (for expressional index columns), and (b) we want
05016      * to allow SET STATISTICS on system catalogs without requiring
05017      * allowSystemTableMods to be turned on.
05018      */
05019     if (rel->rd_rel->relkind != RELKIND_RELATION &&
05020         rel->rd_rel->relkind != RELKIND_MATVIEW &&
05021         rel->rd_rel->relkind != RELKIND_INDEX &&
05022         rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
05023         ereport(ERROR,
05024                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
05025                  errmsg("\"%s\" is not a table, materialized view, index, or foreign table",
05026                         RelationGetRelationName(rel))));
05027 
05028     /* Permissions checks */
05029     if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
05030         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
05031                        RelationGetRelationName(rel));
05032 }
05033 
05034 static void
05035 ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
05036 {
05037     int         newtarget;
05038     Relation    attrelation;
05039     HeapTuple   tuple;
05040     Form_pg_attribute attrtuple;
05041 
05042     Assert(IsA(newValue, Integer));
05043     newtarget = intVal(newValue);
05044 
05045     /*
05046      * Limit target to a sane range
05047      */
05048     if (newtarget < -1)
05049     {
05050         ereport(ERROR,
05051                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
05052                  errmsg("statistics target %d is too low",
05053                         newtarget)));
05054     }
05055     else if (newtarget > 10000)
05056     {
05057         newtarget = 10000;
05058         ereport(WARNING,
05059                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
05060                  errmsg("lowering statistics target to %d",
05061                         newtarget)));
05062     }
05063 
05064     attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
05065 
05066     tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
05067 
05068     if (!HeapTupleIsValid(tuple))
05069         ereport(ERROR,
05070                 (errcode(ERRCODE_UNDEFINED_COLUMN),
05071                  errmsg("column \"%s\" of relation \"%s\" does not exist",
05072                         colName, RelationGetRelationName(rel))));
05073     attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
05074 
05075     if (attrtuple->attnum <= 0)
05076         ereport(ERROR,
05077                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
05078                  errmsg("cannot alter system column \"%s\"",
05079                         colName)));
05080 
05081     attrtuple->attstattarget = newtarget;
05082 
05083     simple_heap_update(attrelation, &tuple->t_self, tuple);
05084 
05085     /* keep system catalog indexes current */
05086     CatalogUpdateIndexes(attrelation, tuple);
05087 
05088     InvokeObjectPostAlterHook(RelationRelationId,
05089                               RelationGetRelid(rel),
05090                               attrtuple->attnum);
05091     heap_freetuple(tuple);
05092 
05093     heap_close(attrelation, RowExclusiveLock);
05094 }
05095 
05096 static void
05097 ATExecSetOptions(Relation rel, const char *colName, Node *options,
05098                  bool isReset, LOCKMODE lockmode)
05099 {
05100     Relation    attrelation;
05101     HeapTuple   tuple,
05102                 newtuple;
05103     Form_pg_attribute attrtuple;
05104     Datum       datum,
05105                 newOptions;
05106     bool        isnull;
05107     Datum       repl_val[Natts_pg_attribute];
05108     bool        repl_null[Natts_pg_attribute];
05109     bool        repl_repl[Natts_pg_attribute];
05110 
05111     attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
05112 
05113     tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
05114 
05115     if (!HeapTupleIsValid(tuple))
05116         ereport(ERROR,
05117                 (errcode(ERRCODE_UNDEFINED_COLUMN),
05118                  errmsg("column \"%s\" of relation \"%s\" does not exist",
05119                         colName, RelationGetRelationName(rel))));
05120     attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
05121 
05122     if (attrtuple->attnum <= 0)
05123         ereport(ERROR,
05124                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
05125                  errmsg("cannot alter system column \"%s\"",
05126                         colName)));
05127 
05128     /* Generate new proposed attoptions (text array) */
05129     Assert(IsA(options, List));
05130     datum = SysCacheGetAttr(ATTNAME, tuple, Anum_pg_attribute_attoptions,
05131                             &isnull);
05132     newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
05133                                      (List *) options, NULL, NULL, false,
05134                                      isReset);
05135     /* Validate new options */
05136     (void) attribute_reloptions(newOptions, true);
05137 
05138     /* Build new tuple. */
05139     memset(repl_null, false, sizeof(repl_null));
05140     memset(repl_repl, false, sizeof(repl_repl));
05141     if (newOptions != (Datum) 0)
05142         repl_val[Anum_pg_attribute_attoptions - 1] = newOptions;
05143     else
05144         repl_null[Anum_pg_attribute_attoptions - 1] = true;
05145     repl_repl[Anum_pg_attribute_attoptions - 1] = true;
05146     newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation),
05147                                  repl_val, repl_null, repl_repl);
05148 
05149     /* Update system catalog. */
05150     simple_heap_update(attrelation, &newtuple->t_self, newtuple);
05151     CatalogUpdateIndexes(attrelation, newtuple);
05152 
05153     InvokeObjectPostAlterHook(RelationRelationId,
05154                               RelationGetRelid(rel),
05155                               attrtuple->attnum);
05156     heap_freetuple(newtuple);
05157 
05158     ReleaseSysCache(tuple);
05159 
05160     heap_close(attrelation, RowExclusiveLock);
05161 }
05162 
05163 /*
05164  * ALTER TABLE ALTER COLUMN SET STORAGE
05165  */
05166 static void
05167 ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE lockmode)
05168 {
05169     char       *storagemode;
05170     char        newstorage;
05171     Relation    attrelation;
05172     HeapTuple   tuple;
05173     Form_pg_attribute attrtuple;
05174 
05175     Assert(IsA(newValue, String));
05176     storagemode = strVal(newValue);
05177 
05178     if (pg_strcasecmp(storagemode, "plain") == 0)
05179         newstorage = 'p';
05180     else if (pg_strcasecmp(storagemode, "external") == 0)
05181         newstorage = 'e';
05182     else if (pg_strcasecmp(storagemode, "extended") == 0)
05183         newstorage = 'x';
05184     else if (pg_strcasecmp(storagemode, "main") == 0)
05185         newstorage = 'm';
05186     else
05187     {
05188         ereport(ERROR,
05189                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
05190                  errmsg("invalid storage type \"%s\"",
05191                         storagemode)));
05192         newstorage = 0;         /* keep compiler quiet */
05193     }
05194 
05195     attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
05196 
05197     tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
05198 
05199     if (!HeapTupleIsValid(tuple))
05200         ereport(ERROR,
05201                 (errcode(ERRCODE_UNDEFINED_COLUMN),
05202                  errmsg("column \"%s\" of relation \"%s\" does not exist",
05203                         colName, RelationGetRelationName(rel))));
05204     attrtuple = (Form_pg_attribute) GETSTRUCT(tuple);
05205 
05206     if (attrtuple->attnum <= 0)
05207         ereport(ERROR,
05208                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
05209                  errmsg("cannot alter system column \"%s\"",
05210                         colName)));
05211 
05212     /*
05213      * safety check: do not allow toasted storage modes unless column datatype
05214      * is TOAST-aware.
05215      */
05216     if (newstorage == 'p' || TypeIsToastable(attrtuple->atttypid))
05217         attrtuple->attstorage = newstorage;
05218     else
05219         ereport(ERROR,
05220                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
05221                  errmsg("column data type %s can only have storage PLAIN",
05222                         format_type_be(attrtuple->atttypid))));
05223 
05224     simple_heap_update(attrelation, &tuple->t_self, tuple);
05225 
05226     /* keep system catalog indexes current */
05227     CatalogUpdateIndexes(attrelation, tuple);
05228 
05229     InvokeObjectPostAlterHook(RelationRelationId,
05230                               RelationGetRelid(rel),
05231                               attrtuple->attnum);
05232 
05233     heap_freetuple(tuple);
05234 
05235     heap_close(attrelation, RowExclusiveLock);
05236 }
05237 
05238 
05239 /*
05240  * ALTER TABLE DROP COLUMN
05241  *
05242  * DROP COLUMN cannot use the normal ALTER TABLE recursion mechanism,
05243  * because we have to decide at runtime whether to recurse or not depending
05244  * on whether attinhcount goes to zero or not.  (We can't check this in a
05245  * static pre-pass because it won't handle multiple inheritance situations
05246  * correctly.)
05247  */
05248 static void
05249 ATPrepDropColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
05250                  AlterTableCmd *cmd, LOCKMODE lockmode)
05251 {
05252     if (rel->rd_rel->reloftype && !recursing)
05253         ereport(ERROR,
05254                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
05255                  errmsg("cannot drop column from typed table")));
05256 
05257     if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
05258         ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
05259 
05260     if (recurse)
05261         cmd->subtype = AT_DropColumnRecurse;
05262 }
05263 
05264 static void
05265 ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
05266                  DropBehavior behavior,
05267                  bool recurse, bool recursing,
05268                  bool missing_ok, LOCKMODE lockmode)
05269 {
05270     HeapTuple   tuple;
05271     Form_pg_attribute targetatt;
05272     AttrNumber  attnum;
05273     List       *children;
05274     ObjectAddress object;
05275 
05276     /* At top level, permission check was done in ATPrepCmd, else do it */
05277     if (recursing)
05278         ATSimplePermissions(rel, ATT_TABLE);
05279 
05280     /*
05281      * get the number of the attribute
05282      */
05283     tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
05284     if (!HeapTupleIsValid(tuple))
05285     {
05286         if (!missing_ok)
05287         {
05288             ereport(ERROR,
05289                     (errcode(ERRCODE_UNDEFINED_COLUMN),
05290                      errmsg("column \"%s\" of relation \"%s\" does not exist",
05291                             colName, RelationGetRelationName(rel))));
05292         }
05293         else
05294         {
05295             ereport(NOTICE,
05296                     (errmsg("column \"%s\" of relation \"%s\" does not exist, skipping",
05297                             colName, RelationGetRelationName(rel))));
05298             return;
05299         }
05300     }
05301     targetatt = (Form_pg_attribute) GETSTRUCT(tuple);
05302 
05303     attnum = targetatt->attnum;
05304 
05305     /* Can't drop a system attribute, except OID */
05306     if (attnum <= 0 && attnum != ObjectIdAttributeNumber)
05307         ereport(ERROR,
05308                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
05309                  errmsg("cannot drop system column \"%s\"",
05310                         colName)));
05311 
05312     /* Don't drop inherited columns */
05313     if (targetatt->attinhcount > 0 && !recursing)
05314         ereport(ERROR,
05315                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
05316                  errmsg("cannot drop inherited column \"%s\"",
05317                         colName)));
05318 
05319     ReleaseSysCache(tuple);
05320 
05321     /*
05322      * Propagate to children as appropriate.  Unlike most other ALTER
05323      * routines, we have to do this one level of recursion at a time; we can't
05324      * use find_all_inheritors to do it in one pass.
05325      */
05326     children = find_inheritance_children(RelationGetRelid(rel), lockmode);
05327 
05328     if (children)
05329     {
05330         Relation    attr_rel;
05331         ListCell   *child;
05332 
05333         attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
05334         foreach(child, children)
05335         {
05336             Oid         childrelid = lfirst_oid(child);
05337             Relation    childrel;
05338             Form_pg_attribute childatt;
05339 
05340             /* find_inheritance_children already got lock */
05341             childrel = heap_open(childrelid, NoLock);
05342             CheckTableNotInUse(childrel, "ALTER TABLE");
05343 
05344             tuple = SearchSysCacheCopyAttName(childrelid, colName);
05345             if (!HeapTupleIsValid(tuple))       /* shouldn't happen */
05346                 elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u",
05347                      colName, childrelid);
05348             childatt = (Form_pg_attribute) GETSTRUCT(tuple);
05349 
05350             if (childatt->attinhcount <= 0)     /* shouldn't happen */
05351                 elog(ERROR, "relation %u has non-inherited attribute \"%s\"",
05352                      childrelid, colName);
05353 
05354             if (recurse)
05355             {
05356                 /*
05357                  * If the child column has other definition sources, just
05358                  * decrement its inheritance count; if not, recurse to delete
05359                  * it.
05360                  */
05361                 if (childatt->attinhcount == 1 && !childatt->attislocal)
05362                 {
05363                     /* Time to delete this child column, too */
05364                     ATExecDropColumn(wqueue, childrel, colName,
05365                                      behavior, true, true,
05366                                      false, lockmode);
05367                 }
05368                 else
05369                 {
05370                     /* Child column must survive my deletion */
05371                     childatt->attinhcount--;
05372 
05373                     simple_heap_update(attr_rel, &tuple->t_self, tuple);
05374 
05375                     /* keep the system catalog indexes current */
05376                     CatalogUpdateIndexes(attr_rel, tuple);
05377 
05378                     /* Make update visible */
05379                     CommandCounterIncrement();
05380                 }
05381             }
05382             else
05383             {
05384                 /*
05385                  * If we were told to drop ONLY in this table (no recursion),
05386                  * we need to mark the inheritors' attributes as locally
05387                  * defined rather than inherited.
05388                  */
05389                 childatt->attinhcount--;
05390                 childatt->attislocal = true;
05391 
05392                 simple_heap_update(attr_rel, &tuple->t_self, tuple);
05393 
05394                 /* keep the system catalog indexes current */
05395                 CatalogUpdateIndexes(attr_rel, tuple);
05396 
05397                 /* Make update visible */
05398                 CommandCounterIncrement();
05399             }
05400 
05401             heap_freetuple(tuple);
05402 
05403             heap_close(childrel, NoLock);
05404         }
05405         heap_close(attr_rel, RowExclusiveLock);
05406     }
05407 
05408     /*
05409      * Perform the actual column deletion
05410      */
05411     object.classId = RelationRelationId;
05412     object.objectId = RelationGetRelid(rel);
05413     object.objectSubId = attnum;
05414 
05415     performDeletion(&object, behavior, 0);
05416 
05417     /*
05418      * If we dropped the OID column, must adjust pg_class.relhasoids and tell
05419      * Phase 3 to physically get rid of the column.  We formerly left the
05420      * column in place physically, but this caused subtle problems.  See
05421      * http://archives.postgresql.org/pgsql-hackers/2009-02/msg00363.php
05422      */
05423     if (attnum == ObjectIdAttributeNumber)
05424     {
05425         Relation    class_rel;
05426         Form_pg_class tuple_class;
05427         AlteredTableInfo *tab;
05428 
05429         class_rel = heap_open(RelationRelationId, RowExclusiveLock);
05430 
05431         tuple = SearchSysCacheCopy1(RELOID,
05432                                     ObjectIdGetDatum(RelationGetRelid(rel)));
05433         if (!HeapTupleIsValid(tuple))
05434             elog(ERROR, "cache lookup failed for relation %u",
05435                  RelationGetRelid(rel));
05436         tuple_class = (Form_pg_class) GETSTRUCT(tuple);
05437 
05438         tuple_class->relhasoids = false;
05439         simple_heap_update(class_rel, &tuple->t_self, tuple);
05440 
05441         /* Keep the catalog indexes up to date */
05442         CatalogUpdateIndexes(class_rel, tuple);
05443 
05444         heap_close(class_rel, RowExclusiveLock);
05445 
05446         /* Find or create work queue entry for this table */
05447         tab = ATGetQueueEntry(wqueue, rel);
05448 
05449         /* Tell Phase 3 to physically remove the OID column */
05450         tab->rewrite = true;
05451     }
05452 }
05453 
05454 /*
05455  * ALTER TABLE ADD INDEX
05456  *
05457  * There is no such command in the grammar, but parse_utilcmd.c converts
05458  * UNIQUE and PRIMARY KEY constraints into AT_AddIndex subcommands.  This lets
05459  * us schedule creation of the index at the appropriate time during ALTER.
05460  */
05461 static void
05462 ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
05463                IndexStmt *stmt, bool is_rebuild, LOCKMODE lockmode)
05464 {
05465     bool        check_rights;
05466     bool        skip_build;
05467     bool        quiet;
05468     Oid         new_index;
05469 
05470     Assert(IsA(stmt, IndexStmt));
05471     Assert(!stmt->concurrent);
05472 
05473     /* suppress schema rights check when rebuilding existing index */
05474     check_rights = !is_rebuild;
05475     /* skip index build if phase 3 will do it or we're reusing an old one */
05476     skip_build = tab->rewrite || OidIsValid(stmt->oldNode);
05477     /* suppress notices when rebuilding existing index */
05478     quiet = is_rebuild;
05479 
05480     /* The IndexStmt has already been through transformIndexStmt */
05481 
05482     new_index = DefineIndex(stmt,
05483                             InvalidOid, /* no predefined OID */
05484                             true,       /* is_alter_table */
05485                             check_rights,
05486                             skip_build,
05487                             quiet);
05488 
05489     /*
05490      * If TryReuseIndex() stashed a relfilenode for us, we used it for the new
05491      * index instead of building from scratch.  The DROP of the old edition of
05492      * this index will have scheduled the storage for deletion at commit, so
05493      * cancel that pending deletion.
05494      */
05495     if (OidIsValid(stmt->oldNode))
05496     {
05497         Relation    irel = index_open(new_index, NoLock);
05498 
05499         RelationPreserveStorage(irel->rd_node, true);
05500         index_close(irel, NoLock);
05501     }
05502 }
05503 
05504 /*
05505  * ALTER TABLE ADD CONSTRAINT USING INDEX
05506  */
05507 static void
05508 ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
05509                          IndexStmt *stmt, LOCKMODE lockmode)
05510 {
05511     Oid         index_oid = stmt->indexOid;
05512     Relation    indexRel;
05513     char       *indexName;
05514     IndexInfo  *indexInfo;
05515     char       *constraintName;
05516     char        constraintType;
05517 
05518     Assert(IsA(stmt, IndexStmt));
05519     Assert(OidIsValid(index_oid));
05520     Assert(stmt->isconstraint);
05521 
05522     indexRel = index_open(index_oid, AccessShareLock);
05523 
05524     indexName = pstrdup(RelationGetRelationName(indexRel));
05525 
05526     indexInfo = BuildIndexInfo(indexRel);
05527 
05528     /* this should have been checked at parse time */
05529     if (!indexInfo->ii_Unique)
05530         elog(ERROR, "index \"%s\" is not unique", indexName);
05531 
05532     /*
05533      * Determine name to assign to constraint.  We require a constraint to
05534      * have the same name as the underlying index; therefore, use the index's
05535      * existing name as the default constraint name, and if the user
05536      * explicitly gives some other name for the constraint, rename the index
05537      * to match.
05538      */
05539     constraintName = stmt->idxname;
05540     if (constraintName == NULL)
05541         constraintName = indexName;
05542     else if (strcmp(constraintName, indexName) != 0)
05543     {
05544         ereport(NOTICE,
05545                 (errmsg("ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"",
05546                         indexName, constraintName)));
05547         RenameRelationInternal(index_oid, constraintName, false);
05548     }
05549 
05550     /* Extra checks needed if making primary key */
05551     if (stmt->primary)
05552         index_check_primary_key(rel, indexInfo, true);
05553 
05554     /* Note we currently don't support EXCLUSION constraints here */
05555     if (stmt->primary)
05556         constraintType = CONSTRAINT_PRIMARY;
05557     else
05558         constraintType = CONSTRAINT_UNIQUE;
05559 
05560     /* Create the catalog entries for the constraint */
05561     index_constraint_create(rel,
05562                             index_oid,
05563                             indexInfo,
05564                             constraintName,
05565                             constraintType,
05566                             stmt->deferrable,
05567                             stmt->initdeferred,
05568                             stmt->primary,
05569                             true, /* update pg_index */
05570                             true, /* remove old dependencies */
05571                             allowSystemTableMods,
05572                             false); /* is_internal */
05573 
05574     index_close(indexRel, NoLock);
05575 }
05576 
05577 /*
05578  * ALTER TABLE ADD CONSTRAINT
05579  */
05580 static void
05581 ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
05582                     Constraint *newConstraint, bool recurse, bool is_readd,
05583                     LOCKMODE lockmode)
05584 {
05585     Assert(IsA(newConstraint, Constraint));
05586 
05587     /*
05588      * Currently, we only expect to see CONSTR_CHECK and CONSTR_FOREIGN nodes
05589      * arriving here (see the preprocessing done in parse_utilcmd.c).  Use a
05590      * switch anyway to make it easier to add more code later.
05591      */
05592     switch (newConstraint->contype)
05593     {
05594         case CONSTR_CHECK:
05595             ATAddCheckConstraint(wqueue, tab, rel,
05596                                  newConstraint, recurse, false, is_readd,
05597                                  lockmode);
05598             break;
05599 
05600         case CONSTR_FOREIGN:
05601 
05602             /*
05603              * Note that we currently never recurse for FK constraints, so the
05604              * "recurse" flag is silently ignored.
05605              *
05606              * Assign or validate constraint name
05607              */
05608             if (newConstraint->conname)
05609             {
05610                 if (ConstraintNameIsUsed(CONSTRAINT_RELATION,
05611                                          RelationGetRelid(rel),
05612                                          RelationGetNamespace(rel),
05613                                          newConstraint->conname))
05614                     ereport(ERROR,
05615                             (errcode(ERRCODE_DUPLICATE_OBJECT),
05616                              errmsg("constraint \"%s\" for relation \"%s\" already exists",
05617                                     newConstraint->conname,
05618                                     RelationGetRelationName(rel))));
05619             }
05620             else
05621                 newConstraint->conname =
05622                     ChooseConstraintName(RelationGetRelationName(rel),
05623                                    strVal(linitial(newConstraint->fk_attrs)),
05624                                          "fkey",
05625                                          RelationGetNamespace(rel),
05626                                          NIL);
05627 
05628             ATAddForeignKeyConstraint(tab, rel, newConstraint, lockmode);
05629             break;
05630 
05631         default:
05632             elog(ERROR, "unrecognized constraint type: %d",
05633                  (int) newConstraint->contype);
05634     }
05635 }
05636 
05637 /*
05638  * Add a check constraint to a single table and its children
05639  *
05640  * Subroutine for ATExecAddConstraint.
05641  *
05642  * We must recurse to child tables during execution, rather than using
05643  * ALTER TABLE's normal prep-time recursion.  The reason is that all the
05644  * constraints *must* be given the same name, else they won't be seen as
05645  * related later.  If the user didn't explicitly specify a name, then
05646  * AddRelationNewConstraints would normally assign different names to the
05647  * child constraints.  To fix that, we must capture the name assigned at
05648  * the parent table and pass that down.
05649  *
05650  * When re-adding a previously existing constraint (during ALTER COLUMN TYPE),
05651  * we don't need to recurse here, because recursion will be carried out at a
05652  * higher level; the constraint name issue doesn't apply because the names
05653  * have already been assigned and are just being re-used.  We need a separate
05654  * "is_readd" flag for that; just setting recurse=false would result in an
05655  * error if there are child tables.
05656  */
05657 static void
05658 ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
05659                      Constraint *constr, bool recurse, bool recursing,
05660                      bool is_readd, LOCKMODE lockmode)
05661 {
05662     List       *newcons;
05663     ListCell   *lcon;
05664     List       *children;
05665     ListCell   *child;
05666 
05667     /* At top level, permission check was done in ATPrepCmd, else do it */
05668     if (recursing)
05669         ATSimplePermissions(rel, ATT_TABLE);
05670 
05671     /*
05672      * Call AddRelationNewConstraints to do the work, making sure it works on
05673      * a copy of the Constraint so transformExpr can't modify the original. It
05674      * returns a list of cooked constraints.
05675      *
05676      * If the constraint ends up getting merged with a pre-existing one, it's
05677      * omitted from the returned list, which is what we want: we do not need
05678      * to do any validation work.  That can only happen at child tables,
05679      * though, since we disallow merging at the top level.
05680      */
05681     newcons = AddRelationNewConstraints(rel, NIL,
05682                                         list_make1(copyObject(constr)),
05683                                         recursing,      /* allow_merge */
05684                                         !recursing,     /* is_local */
05685                                         is_readd);      /* is_internal */
05686 
05687     /* Add each to-be-validated constraint to Phase 3's queue */
05688     foreach(lcon, newcons)
05689     {
05690         CookedConstraint *ccon = (CookedConstraint *) lfirst(lcon);
05691 
05692         if (!ccon->skip_validation)
05693         {
05694             NewConstraint *newcon;
05695 
05696             newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
05697             newcon->name = ccon->name;
05698             newcon->contype = ccon->contype;
05699             /* ExecQual wants implicit-AND format */
05700             newcon->qual = (Node *) make_ands_implicit((Expr *) ccon->expr);
05701 
05702             tab->constraints = lappend(tab->constraints, newcon);
05703         }
05704 
05705         /* Save the actually assigned name if it was defaulted */
05706         if (constr->conname == NULL)
05707             constr->conname = ccon->name;
05708     }
05709 
05710     /* At this point we must have a locked-down name to use */
05711     Assert(constr->conname != NULL);
05712 
05713     /* Advance command counter in case same table is visited multiple times */
05714     CommandCounterIncrement();
05715 
05716     /*
05717      * If the constraint got merged with an existing constraint, we're done.
05718      * We mustn't recurse to child tables in this case, because they've
05719      * already got the constraint, and visiting them again would lead to an
05720      * incorrect value for coninhcount.
05721      */
05722     if (newcons == NIL)
05723         return;
05724 
05725     /*
05726      * If adding a NO INHERIT constraint, no need to find our children.
05727      * Likewise, in a re-add operation, we don't need to recurse (that will be
05728      * handled at higher levels).
05729      */
05730     if (constr->is_no_inherit || is_readd)
05731         return;
05732 
05733     /*
05734      * Propagate to children as appropriate.  Unlike most other ALTER
05735      * routines, we have to do this one level of recursion at a time; we can't
05736      * use find_all_inheritors to do it in one pass.
05737      */
05738     children = find_inheritance_children(RelationGetRelid(rel), lockmode);
05739 
05740     /*
05741      * Check if ONLY was specified with ALTER TABLE.  If so, allow the
05742      * contraint creation only if there are no children currently.  Error out
05743      * otherwise.
05744      */
05745     if (!recurse && children != NIL)
05746         ereport(ERROR,
05747                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
05748                  errmsg("constraint must be added to child tables too")));
05749 
05750     foreach(child, children)
05751     {
05752         Oid         childrelid = lfirst_oid(child);
05753         Relation    childrel;
05754         AlteredTableInfo *childtab;
05755 
05756         /* find_inheritance_children already got lock */
05757         childrel = heap_open(childrelid, NoLock);
05758         CheckTableNotInUse(childrel, "ALTER TABLE");
05759 
05760         /* Find or create work queue entry for this table */
05761         childtab = ATGetQueueEntry(wqueue, childrel);
05762 
05763         /* Recurse to child */
05764         ATAddCheckConstraint(wqueue, childtab, childrel,
05765                              constr, recurse, true, is_readd, lockmode);
05766 
05767         heap_close(childrel, NoLock);
05768     }
05769 }
05770 
05771 /*
05772  * Add a foreign-key constraint to a single table
05773  *
05774  * Subroutine for ATExecAddConstraint.  Must already hold exclusive
05775  * lock on the rel, and have done appropriate validity checks for it.
05776  * We do permissions checks here, however.
05777  */
05778 static void
05779 ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
05780                           Constraint *fkconstraint, LOCKMODE lockmode)
05781 {
05782     Relation    pkrel;
05783     int16       pkattnum[INDEX_MAX_KEYS];
05784     int16       fkattnum[INDEX_MAX_KEYS];
05785     Oid         pktypoid[INDEX_MAX_KEYS];
05786     Oid         fktypoid[INDEX_MAX_KEYS];
05787     Oid         opclasses[INDEX_MAX_KEYS];
05788     Oid         pfeqoperators[INDEX_MAX_KEYS];
05789     Oid         ppeqoperators[INDEX_MAX_KEYS];
05790     Oid         ffeqoperators[INDEX_MAX_KEYS];
05791     int         i;
05792     int         numfks,
05793                 numpks;
05794     Oid         indexOid;
05795     Oid         constrOid;
05796     bool        old_check_ok;
05797     ListCell   *old_pfeqop_item = list_head(fkconstraint->old_conpfeqop);
05798 
05799     /*
05800      * Grab an exclusive lock on the pk table, so that someone doesn't delete
05801      * rows out from under us. (Although a lesser lock would do for that
05802      * purpose, we'll need exclusive lock anyway to add triggers to the pk
05803      * table; trying to start with a lesser lock will just create a risk of
05804      * deadlock.)
05805      */
05806     pkrel = heap_openrv(fkconstraint->pktable, AccessExclusiveLock);
05807 
05808     /*
05809      * Validity checks (permission checks wait till we have the column
05810      * numbers)
05811      */
05812     if (pkrel->rd_rel->relkind != RELKIND_RELATION)
05813         ereport(ERROR,
05814                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
05815                  errmsg("referenced relation \"%s\" is not a table",
05816                         RelationGetRelationName(pkrel))));
05817 
05818     if (!allowSystemTableMods && IsSystemRelation(pkrel))
05819         ereport(ERROR,
05820                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
05821                  errmsg("permission denied: \"%s\" is a system catalog",
05822                         RelationGetRelationName(pkrel))));
05823 
05824     /*
05825      * References from permanent or unlogged tables to temp tables, and from
05826      * permanent tables to unlogged tables, are disallowed because the
05827      * referenced data can vanish out from under us.  References from temp
05828      * tables to any other table type are also disallowed, because other
05829      * backends might need to run the RI triggers on the perm table, but they
05830      * can't reliably see tuples in the local buffers of other backends.
05831      */
05832     switch (rel->rd_rel->relpersistence)
05833     {
05834         case RELPERSISTENCE_PERMANENT:
05835             if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT)
05836                 ereport(ERROR,
05837                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
05838                          errmsg("constraints on permanent tables may reference only permanent tables")));
05839             break;
05840         case RELPERSISTENCE_UNLOGGED:
05841             if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT
05842                 && pkrel->rd_rel->relpersistence != RELPERSISTENCE_UNLOGGED)
05843                 ereport(ERROR,
05844                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
05845                          errmsg("constraints on unlogged tables may reference only permanent or unlogged tables")));
05846             break;
05847         case RELPERSISTENCE_TEMP:
05848             if (pkrel->rd_rel->relpersistence != RELPERSISTENCE_TEMP)
05849                 ereport(ERROR,
05850                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
05851                          errmsg("constraints on temporary tables may reference only temporary tables")));
05852             if (!pkrel->rd_islocaltemp || !rel->rd_islocaltemp)
05853                 ereport(ERROR,
05854                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
05855                          errmsg("constraints on temporary tables must involve temporary tables of this session")));
05856             break;
05857     }
05858 
05859     /*
05860      * Look up the referencing attributes to make sure they exist, and record
05861      * their attnums and type OIDs.
05862      */
05863     MemSet(pkattnum, 0, sizeof(pkattnum));
05864     MemSet(fkattnum, 0, sizeof(fkattnum));
05865     MemSet(pktypoid, 0, sizeof(pktypoid));
05866     MemSet(fktypoid, 0, sizeof(fktypoid));
05867     MemSet(opclasses, 0, sizeof(opclasses));
05868     MemSet(pfeqoperators, 0, sizeof(pfeqoperators));
05869     MemSet(ppeqoperators, 0, sizeof(ppeqoperators));
05870     MemSet(ffeqoperators, 0, sizeof(ffeqoperators));
05871 
05872     numfks = transformColumnNameList(RelationGetRelid(rel),
05873                                      fkconstraint->fk_attrs,
05874                                      fkattnum, fktypoid);
05875 
05876     /*
05877      * If the attribute list for the referenced table was omitted, lookup the
05878      * definition of the primary key and use it.  Otherwise, validate the
05879      * supplied attribute list.  In either case, discover the index OID and
05880      * index opclasses, and the attnums and type OIDs of the attributes.
05881      */
05882     if (fkconstraint->pk_attrs == NIL)
05883     {
05884         numpks = transformFkeyGetPrimaryKey(pkrel, &indexOid,
05885                                             &fkconstraint->pk_attrs,
05886                                             pkattnum, pktypoid,
05887                                             opclasses);
05888     }
05889     else
05890     {
05891         numpks = transformColumnNameList(RelationGetRelid(pkrel),
05892                                          fkconstraint->pk_attrs,
05893                                          pkattnum, pktypoid);
05894         /* Look for an index matching the column list */
05895         indexOid = transformFkeyCheckAttrs(pkrel, numpks, pkattnum,
05896                                            opclasses);
05897     }
05898 
05899     /*
05900      * Now we can check permissions.
05901      */
05902     checkFkeyPermissions(pkrel, pkattnum, numpks);
05903     checkFkeyPermissions(rel, fkattnum, numfks);
05904 
05905     /*
05906      * Look up the equality operators to use in the constraint.
05907      *
05908      * Note that we have to be careful about the difference between the actual
05909      * PK column type and the opclass' declared input type, which might be
05910      * only binary-compatible with it.  The declared opcintype is the right
05911      * thing to probe pg_amop with.
05912      */
05913     if (numfks != numpks)
05914         ereport(ERROR,
05915                 (errcode(ERRCODE_INVALID_FOREIGN_KEY),
05916                  errmsg("number of referencing and referenced columns for foreign key disagree")));
05917 
05918     /*
05919      * On the strength of a previous constraint, we might avoid scanning
05920      * tables to validate this one.  See below.
05921      */
05922     old_check_ok = (fkconstraint->old_conpfeqop != NIL);
05923     Assert(!old_check_ok || numfks == list_length(fkconstraint->old_conpfeqop));
05924 
05925     for (i = 0; i < numpks; i++)
05926     {
05927         Oid         pktype = pktypoid[i];
05928         Oid         fktype = fktypoid[i];
05929         Oid         fktyped;
05930         HeapTuple   cla_ht;
05931         Form_pg_opclass cla_tup;
05932         Oid         amid;
05933         Oid         opfamily;
05934         Oid         opcintype;
05935         Oid         pfeqop;
05936         Oid         ppeqop;
05937         Oid         ffeqop;
05938         int16       eqstrategy;
05939         Oid         pfeqop_right;
05940 
05941         /* We need several fields out of the pg_opclass entry */
05942         cla_ht = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclasses[i]));
05943         if (!HeapTupleIsValid(cla_ht))
05944             elog(ERROR, "cache lookup failed for opclass %u", opclasses[i]);
05945         cla_tup = (Form_pg_opclass) GETSTRUCT(cla_ht);
05946         amid = cla_tup->opcmethod;
05947         opfamily = cla_tup->opcfamily;
05948         opcintype = cla_tup->opcintype;
05949         ReleaseSysCache(cla_ht);
05950 
05951         /*
05952          * Check it's a btree; currently this can never fail since no other
05953          * index AMs support unique indexes.  If we ever did have other types
05954          * of unique indexes, we'd need a way to determine which operator
05955          * strategy number is equality.  (Is it reasonable to insist that
05956          * every such index AM use btree's number for equality?)
05957          */
05958         if (amid != BTREE_AM_OID)
05959             elog(ERROR, "only b-tree indexes are supported for foreign keys");
05960         eqstrategy = BTEqualStrategyNumber;
05961 
05962         /*
05963          * There had better be a primary equality operator for the index.
05964          * We'll use it for PK = PK comparisons.
05965          */
05966         ppeqop = get_opfamily_member(opfamily, opcintype, opcintype,
05967                                      eqstrategy);
05968 
05969         if (!OidIsValid(ppeqop))
05970             elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
05971                  eqstrategy, opcintype, opcintype, opfamily);
05972 
05973         /*
05974          * Are there equality operators that take exactly the FK type? Assume
05975          * we should look through any domain here.
05976          */
05977         fktyped = getBaseType(fktype);
05978 
05979         pfeqop = get_opfamily_member(opfamily, opcintype, fktyped,
05980                                      eqstrategy);
05981         if (OidIsValid(pfeqop))
05982         {
05983             pfeqop_right = fktyped;
05984             ffeqop = get_opfamily_member(opfamily, fktyped, fktyped,
05985                                          eqstrategy);
05986         }
05987         else
05988         {
05989             /* keep compiler quiet */
05990             pfeqop_right = InvalidOid;
05991             ffeqop = InvalidOid;
05992         }
05993 
05994         if (!(OidIsValid(pfeqop) && OidIsValid(ffeqop)))
05995         {
05996             /*
05997              * Otherwise, look for an implicit cast from the FK type to the
05998              * opcintype, and if found, use the primary equality operator.
05999              * This is a bit tricky because opcintype might be a polymorphic
06000              * type such as ANYARRAY or ANYENUM; so what we have to test is
06001              * whether the two actual column types can be concurrently cast to
06002              * that type.  (Otherwise, we'd fail to reject combinations such
06003              * as int[] and point[].)
06004              */
06005             Oid         input_typeids[2];
06006             Oid         target_typeids[2];
06007 
06008             input_typeids[0] = pktype;
06009             input_typeids[1] = fktype;
06010             target_typeids[0] = opcintype;
06011             target_typeids[1] = opcintype;
06012             if (can_coerce_type(2, input_typeids, target_typeids,
06013                                 COERCION_IMPLICIT))
06014             {
06015                 pfeqop = ffeqop = ppeqop;
06016                 pfeqop_right = opcintype;
06017             }
06018         }
06019 
06020         if (!(OidIsValid(pfeqop) && OidIsValid(ffeqop)))
06021             ereport(ERROR,
06022                     (errcode(ERRCODE_DATATYPE_MISMATCH),
06023                      errmsg("foreign key constraint \"%s\" "
06024                             "cannot be implemented",
06025                             fkconstraint->conname),
06026                      errdetail("Key columns \"%s\" and \"%s\" "
06027                                "are of incompatible types: %s and %s.",
06028                                strVal(list_nth(fkconstraint->fk_attrs, i)),
06029                                strVal(list_nth(fkconstraint->pk_attrs, i)),
06030                                format_type_be(fktype),
06031                                format_type_be(pktype))));
06032 
06033         if (old_check_ok)
06034         {
06035             /*
06036              * When a pfeqop changes, revalidate the constraint.  We could
06037              * permit intra-opfamily changes, but that adds subtle complexity
06038              * without any concrete benefit for core types.  We need not
06039              * assess ppeqop or ffeqop, which RI_Initial_Check() does not use.
06040              */
06041             old_check_ok = (pfeqop == lfirst_oid(old_pfeqop_item));
06042             old_pfeqop_item = lnext(old_pfeqop_item);
06043         }
06044         if (old_check_ok)
06045         {
06046             Oid         old_fktype;
06047             Oid         new_fktype;
06048             CoercionPathType old_pathtype;
06049             CoercionPathType new_pathtype;
06050             Oid         old_castfunc;
06051             Oid         new_castfunc;
06052 
06053             /*
06054              * Identify coercion pathways from each of the old and new FK-side
06055              * column types to the right (foreign) operand type of the pfeqop.
06056              * We may assume that pg_constraint.conkey is not changing.
06057              */
06058             old_fktype = tab->oldDesc->attrs[fkattnum[i] - 1]->atttypid;
06059             new_fktype = fktype;
06060             old_pathtype = findFkeyCast(pfeqop_right, old_fktype,
06061                                         &old_castfunc);
06062             new_pathtype = findFkeyCast(pfeqop_right, new_fktype,
06063                                         &new_castfunc);
06064 
06065             /*
06066              * Upon a change to the cast from the FK column to its pfeqop
06067              * operand, revalidate the constraint.  For this evaluation, a
06068              * binary coercion cast is equivalent to no cast at all.  While
06069              * type implementors should design implicit casts with an eye
06070              * toward consistency of operations like equality, we cannot
06071              * assume here that they have done so.
06072              *
06073              * A function with a polymorphic argument could change behavior
06074              * arbitrarily in response to get_fn_expr_argtype().  Therefore,
06075              * when the cast destination is polymorphic, we only avoid
06076              * revalidation if the input type has not changed at all.  Given
06077              * just the core data types and operator classes, this requirement
06078              * prevents no would-be optimizations.
06079              *
06080              * If the cast converts from a base type to a domain thereon, then
06081              * that domain type must be the opcintype of the unique index.
06082              * Necessarily, the primary key column must then be of the domain
06083              * type.  Since the constraint was previously valid, all values on
06084              * the foreign side necessarily exist on the primary side and in
06085              * turn conform to the domain.  Consequently, we need not treat
06086              * domains specially here.
06087              *
06088              * Since we require that all collations share the same notion of
06089              * equality (which they do, because texteq reduces to bitwise
06090              * equality), we don't compare collation here.
06091              *
06092              * We need not directly consider the PK type.  It's necessarily
06093              * binary coercible to the opcintype of the unique index column,
06094              * and ri_triggers.c will only deal with PK datums in terms of
06095              * that opcintype.  Changing the opcintype also changes pfeqop.
06096              */
06097             old_check_ok = (new_pathtype == old_pathtype &&
06098                             new_castfunc == old_castfunc &&
06099                             (!IsPolymorphicType(pfeqop_right) ||
06100                              new_fktype == old_fktype));
06101 
06102         }
06103 
06104         pfeqoperators[i] = pfeqop;
06105         ppeqoperators[i] = ppeqop;
06106         ffeqoperators[i] = ffeqop;
06107     }
06108 
06109     /*
06110      * Record the FK constraint in pg_constraint.
06111      */
06112     constrOid = CreateConstraintEntry(fkconstraint->conname,
06113                                       RelationGetNamespace(rel),
06114                                       CONSTRAINT_FOREIGN,
06115                                       fkconstraint->deferrable,
06116                                       fkconstraint->initdeferred,
06117                                       fkconstraint->initially_valid,
06118                                       RelationGetRelid(rel),
06119                                       fkattnum,
06120                                       numfks,
06121                                       InvalidOid,       /* not a domain
06122                                                          * constraint */
06123                                       indexOid,
06124                                       RelationGetRelid(pkrel),
06125                                       pkattnum,
06126                                       pfeqoperators,
06127                                       ppeqoperators,
06128                                       ffeqoperators,
06129                                       numpks,
06130                                       fkconstraint->fk_upd_action,
06131                                       fkconstraint->fk_del_action,
06132                                       fkconstraint->fk_matchtype,
06133                                       NULL,     /* no exclusion constraint */
06134                                       NULL,     /* no check constraint */
06135                                       NULL,
06136                                       NULL,
06137                                       true,     /* islocal */
06138                                       0,        /* inhcount */
06139                                       true,     /* isnoinherit */
06140                                       false);   /* is_internal */
06141 
06142     /*
06143      * Create the triggers that will enforce the constraint.
06144      */
06145     createForeignKeyTriggers(rel, fkconstraint, constrOid, indexOid);
06146 
06147     /*
06148      * Tell Phase 3 to check that the constraint is satisfied by existing
06149      * rows. We can skip this during table creation, when requested explicitly
06150      * by specifying NOT VALID in an ADD FOREIGN KEY command, and when we're
06151      * recreating a constraint following a SET DATA TYPE operation that did
06152      * not impugn its validity.
06153      */
06154     if (!old_check_ok && !fkconstraint->skip_validation)
06155     {
06156         NewConstraint *newcon;
06157 
06158         newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
06159         newcon->name = fkconstraint->conname;
06160         newcon->contype = CONSTR_FOREIGN;
06161         newcon->refrelid = RelationGetRelid(pkrel);
06162         newcon->refindid = indexOid;
06163         newcon->conid = constrOid;
06164         newcon->qual = (Node *) fkconstraint;
06165 
06166         tab->constraints = lappend(tab->constraints, newcon);
06167     }
06168 
06169     /*
06170      * Close pk table, but keep lock until we've committed.
06171      */
06172     heap_close(pkrel, NoLock);
06173 }
06174 
06175 /*
06176  * ALTER TABLE VALIDATE CONSTRAINT
06177  *
06178  * XXX The reason we handle recursion here rather than at Phase 1 is because
06179  * there's no good way to skip recursing when handling foreign keys: there is
06180  * no need to lock children in that case, yet we wouldn't be able to avoid
06181  * doing so at that level.
06182  */
06183 static void
06184 ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
06185                          bool recursing, LOCKMODE lockmode)
06186 {
06187     Relation    conrel;
06188     SysScanDesc scan;
06189     ScanKeyData key;
06190     HeapTuple   tuple;
06191     Form_pg_constraint con = NULL;
06192     bool        found = false;
06193 
06194     conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
06195 
06196     /*
06197      * Find and check the target constraint
06198      */
06199     ScanKeyInit(&key,
06200                 Anum_pg_constraint_conrelid,
06201                 BTEqualStrategyNumber, F_OIDEQ,
06202                 ObjectIdGetDatum(RelationGetRelid(rel)));
06203     scan = systable_beginscan(conrel, ConstraintRelidIndexId,
06204                               true, SnapshotNow, 1, &key);
06205 
06206     while (HeapTupleIsValid(tuple = systable_getnext(scan)))
06207     {
06208         con = (Form_pg_constraint) GETSTRUCT(tuple);
06209         if (strcmp(NameStr(con->conname), constrName) == 0)
06210         {
06211             found = true;
06212             break;
06213         }
06214     }
06215 
06216     if (!found)
06217         ereport(ERROR,
06218                 (errcode(ERRCODE_UNDEFINED_OBJECT),
06219                  errmsg("constraint \"%s\" of relation \"%s\" does not exist",
06220                         constrName, RelationGetRelationName(rel))));
06221 
06222     if (con->contype != CONSTRAINT_FOREIGN &&
06223         con->contype != CONSTRAINT_CHECK)
06224         ereport(ERROR,
06225                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
06226                  errmsg("constraint \"%s\" of relation \"%s\" is not a foreign key or check constraint",
06227                         constrName, RelationGetRelationName(rel))));
06228 
06229     if (!con->convalidated)
06230     {
06231         HeapTuple   copyTuple;
06232         Form_pg_constraint copy_con;
06233 
06234         if (con->contype == CONSTRAINT_FOREIGN)
06235         {
06236             Oid         conid = HeapTupleGetOid(tuple);
06237             Relation    refrel;
06238 
06239             /*
06240              * Triggers are already in place on both tables, so a concurrent
06241              * write that alters the result here is not possible. Normally we
06242              * can run a query here to do the validation, which would only
06243              * require AccessShareLock. In some cases, it is possible that we
06244              * might need to fire triggers to perform the check, so we take a
06245              * lock at RowShareLock level just in case.
06246              */
06247             refrel = heap_open(con->confrelid, RowShareLock);
06248 
06249             validateForeignKeyConstraint(constrName, rel, refrel,
06250                                          con->conindid,
06251                                          conid);
06252             heap_close(refrel, NoLock);
06253 
06254             /*
06255              * Foreign keys do not inherit, so we purposely ignore the
06256              * recursion bit here
06257              */
06258         }
06259         else if (con->contype == CONSTRAINT_CHECK)
06260         {
06261             List       *children = NIL;
06262             ListCell   *child;
06263 
06264             /*
06265              * If we're recursing, the parent has already done this, so skip
06266              * it.
06267              */
06268             if (!recursing)
06269                 children = find_all_inheritors(RelationGetRelid(rel),
06270                                                lockmode, NULL);
06271 
06272             /*
06273              * For CHECK constraints, we must ensure that we only mark the
06274              * constraint as validated on the parent if it's already validated
06275              * on the children.
06276              *
06277              * We recurse before validating on the parent, to reduce risk of
06278              * deadlocks.
06279              */
06280             foreach(child, children)
06281             {
06282                 Oid         childoid = lfirst_oid(child);
06283                 Relation    childrel;
06284 
06285                 if (childoid == RelationGetRelid(rel))
06286                     continue;
06287 
06288                 /*
06289                  * If we are told not to recurse, there had better not be any
06290                  * child tables; else the addition would put them out of step.
06291                  */
06292                 if (!recurse)
06293                     ereport(ERROR,
06294                             (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
06295                              errmsg("constraint must be validated on child tables too")));
06296 
06297                 /* find_all_inheritors already got lock */
06298                 childrel = heap_open(childoid, NoLock);
06299 
06300                 ATExecValidateConstraint(childrel, constrName, false,
06301                                          true, lockmode);
06302                 heap_close(childrel, NoLock);
06303             }
06304 
06305             validateCheckConstraint(rel, tuple);
06306 
06307             /*
06308              * Invalidate relcache so that others see the new validated
06309              * constraint.
06310              */
06311             CacheInvalidateRelcache(rel);
06312         }
06313 
06314         /*
06315          * Now update the catalog, while we have the door open.
06316          */
06317         copyTuple = heap_copytuple(tuple);
06318         copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
06319         copy_con->convalidated = true;
06320         simple_heap_update(conrel, &copyTuple->t_self, copyTuple);
06321         CatalogUpdateIndexes(conrel, copyTuple);
06322 
06323         InvokeObjectPostAlterHook(ConstraintRelationId,
06324                                   HeapTupleGetOid(tuple), 0);
06325 
06326         heap_freetuple(copyTuple);
06327     }
06328 
06329     systable_endscan(scan);
06330 
06331     heap_close(conrel, RowExclusiveLock);
06332 }
06333 
06334 
06335 /*
06336  * transformColumnNameList - transform list of column names
06337  *
06338  * Lookup each name and return its attnum and type OID
06339  */
06340 static int
06341 transformColumnNameList(Oid relId, List *colList,
06342                         int16 *attnums, Oid *atttypids)
06343 {
06344     ListCell   *l;
06345     int         attnum;
06346 
06347     attnum = 0;
06348     foreach(l, colList)
06349     {
06350         char       *attname = strVal(lfirst(l));
06351         HeapTuple   atttuple;
06352 
06353         atttuple = SearchSysCacheAttName(relId, attname);
06354         if (!HeapTupleIsValid(atttuple))
06355             ereport(ERROR,
06356                     (errcode(ERRCODE_UNDEFINED_COLUMN),
06357                      errmsg("column \"%s\" referenced in foreign key constraint does not exist",
06358                             attname)));
06359         if (attnum >= INDEX_MAX_KEYS)
06360             ereport(ERROR,
06361                     (errcode(ERRCODE_TOO_MANY_COLUMNS),
06362                      errmsg("cannot have more than %d keys in a foreign key",
06363                             INDEX_MAX_KEYS)));
06364         attnums[attnum] = ((Form_pg_attribute) GETSTRUCT(atttuple))->attnum;
06365         atttypids[attnum] = ((Form_pg_attribute) GETSTRUCT(atttuple))->atttypid;
06366         ReleaseSysCache(atttuple);
06367         attnum++;
06368     }
06369 
06370     return attnum;
06371 }
06372 
06373 /*
06374  * transformFkeyGetPrimaryKey -
06375  *
06376  *  Look up the names, attnums, and types of the primary key attributes
06377  *  for the pkrel.  Also return the index OID and index opclasses of the
06378  *  index supporting the primary key.
06379  *
06380  *  All parameters except pkrel are output parameters.  Also, the function
06381  *  return value is the number of attributes in the primary key.
06382  *
06383  *  Used when the column list in the REFERENCES specification is omitted.
06384  */
06385 static int
06386 transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
06387                            List **attnamelist,
06388                            int16 *attnums, Oid *atttypids,
06389                            Oid *opclasses)
06390 {
06391     List       *indexoidlist;
06392     ListCell   *indexoidscan;
06393     HeapTuple   indexTuple = NULL;
06394     Form_pg_index indexStruct = NULL;
06395     Datum       indclassDatum;
06396     bool        isnull;
06397     oidvector  *indclass;
06398     int         i;
06399 
06400     /*
06401      * Get the list of index OIDs for the table from the relcache, and look up
06402      * each one in the pg_index syscache until we find one marked primary key
06403      * (hopefully there isn't more than one such).  Insist it's valid, too.
06404      */
06405     *indexOid = InvalidOid;
06406 
06407     indexoidlist = RelationGetIndexList(pkrel);
06408 
06409     foreach(indexoidscan, indexoidlist)
06410     {
06411         Oid         indexoid = lfirst_oid(indexoidscan);
06412 
06413         indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
06414         if (!HeapTupleIsValid(indexTuple))
06415             elog(ERROR, "cache lookup failed for index %u", indexoid);
06416         indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
06417         if (indexStruct->indisprimary && IndexIsValid(indexStruct))
06418         {
06419             /*
06420              * Refuse to use a deferrable primary key.  This is per SQL spec,
06421              * and there would be a lot of interesting semantic problems if we
06422              * tried to allow it.
06423              */
06424             if (!indexStruct->indimmediate)
06425                 ereport(ERROR,
06426                         (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
06427                          errmsg("cannot use a deferrable primary key for referenced table \"%s\"",
06428                                 RelationGetRelationName(pkrel))));
06429 
06430             *indexOid = indexoid;
06431             break;
06432         }
06433         ReleaseSysCache(indexTuple);
06434     }
06435 
06436     list_free(indexoidlist);
06437 
06438     /*
06439      * Check that we found it
06440      */
06441     if (!OidIsValid(*indexOid))
06442         ereport(ERROR,
06443                 (errcode(ERRCODE_UNDEFINED_OBJECT),
06444                  errmsg("there is no primary key for referenced table \"%s\"",
06445                         RelationGetRelationName(pkrel))));
06446 
06447     /* Must get indclass the hard way */
06448     indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
06449                                     Anum_pg_index_indclass, &isnull);
06450     Assert(!isnull);
06451     indclass = (oidvector *) DatumGetPointer(indclassDatum);
06452 
06453     /*
06454      * Now build the list of PK attributes from the indkey definition (we
06455      * assume a primary key cannot have expressional elements)
06456      */
06457     *attnamelist = NIL;
06458     for (i = 0; i < indexStruct->indnatts; i++)
06459     {
06460         int         pkattno = indexStruct->indkey.values[i];
06461 
06462         attnums[i] = pkattno;
06463         atttypids[i] = attnumTypeId(pkrel, pkattno);
06464         opclasses[i] = indclass->values[i];
06465         *attnamelist = lappend(*attnamelist,
06466                makeString(pstrdup(NameStr(*attnumAttName(pkrel, pkattno)))));
06467     }
06468 
06469     ReleaseSysCache(indexTuple);
06470 
06471     return i;
06472 }
06473 
06474 /*
06475  * transformFkeyCheckAttrs -
06476  *
06477  *  Make sure that the attributes of a referenced table belong to a unique
06478  *  (or primary key) constraint.  Return the OID of the index supporting
06479  *  the constraint, as well as the opclasses associated with the index
06480  *  columns.
06481  */
06482 static Oid
06483 transformFkeyCheckAttrs(Relation pkrel,
06484                         int numattrs, int16 *attnums,
06485                         Oid *opclasses) /* output parameter */
06486 {
06487     Oid         indexoid = InvalidOid;
06488     bool        found = false;
06489     bool        found_deferrable = false;
06490     List       *indexoidlist;
06491     ListCell   *indexoidscan;
06492 
06493     /*
06494      * Get the list of index OIDs for the table from the relcache, and look up
06495      * each one in the pg_index syscache, and match unique indexes to the list
06496      * of attnums we are given.
06497      */
06498     indexoidlist = RelationGetIndexList(pkrel);
06499 
06500     foreach(indexoidscan, indexoidlist)
06501     {
06502         HeapTuple   indexTuple;
06503         Form_pg_index indexStruct;
06504         int         i,
06505                     j;
06506 
06507         indexoid = lfirst_oid(indexoidscan);
06508         indexTuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(indexoid));
06509         if (!HeapTupleIsValid(indexTuple))
06510             elog(ERROR, "cache lookup failed for index %u", indexoid);
06511         indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
06512 
06513         /*
06514          * Must have the right number of columns; must be unique and not a
06515          * partial index; forget it if there are any expressions, too. Invalid
06516          * indexes are out as well.
06517          */
06518         if (indexStruct->indnatts == numattrs &&
06519             indexStruct->indisunique &&
06520             IndexIsValid(indexStruct) &&
06521             heap_attisnull(indexTuple, Anum_pg_index_indpred) &&
06522             heap_attisnull(indexTuple, Anum_pg_index_indexprs))
06523         {
06524             /* Must get indclass the hard way */
06525             Datum       indclassDatum;
06526             bool        isnull;
06527             oidvector  *indclass;
06528 
06529             indclassDatum = SysCacheGetAttr(INDEXRELID, indexTuple,
06530                                             Anum_pg_index_indclass, &isnull);
06531             Assert(!isnull);
06532             indclass = (oidvector *) DatumGetPointer(indclassDatum);
06533 
06534             /*
06535              * The given attnum list may match the index columns in any order.
06536              * Check that each list is a subset of the other.
06537              */
06538             for (i = 0; i < numattrs; i++)
06539             {
06540                 found = false;
06541                 for (j = 0; j < numattrs; j++)
06542                 {
06543                     if (attnums[i] == indexStruct->indkey.values[j])
06544                     {
06545                         found = true;
06546                         break;
06547                     }
06548                 }
06549                 if (!found)
06550                     break;
06551             }
06552             if (found)
06553             {
06554                 for (i = 0; i < numattrs; i++)
06555                 {
06556                     found = false;
06557                     for (j = 0; j < numattrs; j++)
06558                     {
06559                         if (attnums[j] == indexStruct->indkey.values[i])
06560                         {
06561                             opclasses[j] = indclass->values[i];
06562                             found = true;
06563                             break;
06564                         }
06565                     }
06566                     if (!found)
06567                         break;
06568                 }
06569             }
06570 
06571             /*
06572              * Refuse to use a deferrable unique/primary key.  This is per SQL
06573              * spec, and there would be a lot of interesting semantic problems
06574              * if we tried to allow it.
06575              */
06576             if (found && !indexStruct->indimmediate)
06577             {
06578                 /*
06579                  * Remember that we found an otherwise matching index, so that
06580                  * we can generate a more appropriate error message.
06581                  */
06582                 found_deferrable = true;
06583                 found = false;
06584             }
06585         }
06586         ReleaseSysCache(indexTuple);
06587         if (found)
06588             break;
06589     }
06590 
06591     if (!found)
06592     {
06593         if (found_deferrable)
06594             ereport(ERROR,
06595                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
06596                      errmsg("cannot use a deferrable unique constraint for referenced table \"%s\"",
06597                             RelationGetRelationName(pkrel))));
06598         else
06599             ereport(ERROR,
06600                     (errcode(ERRCODE_INVALID_FOREIGN_KEY),
06601                      errmsg("there is no unique constraint matching given keys for referenced table \"%s\"",
06602                             RelationGetRelationName(pkrel))));
06603     }
06604 
06605     list_free(indexoidlist);
06606 
06607     return indexoid;
06608 }
06609 
06610 /*
06611  * findFkeyCast -
06612  *
06613  *  Wrapper around find_coercion_pathway() for ATAddForeignKeyConstraint().
06614  *  Caller has equal regard for binary coercibility and for an exact match.
06615 */
06616 static CoercionPathType
06617 findFkeyCast(Oid targetTypeId, Oid sourceTypeId, Oid *funcid)
06618 {
06619     CoercionPathType ret;
06620 
06621     if (targetTypeId == sourceTypeId)
06622     {
06623         ret = COERCION_PATH_RELABELTYPE;
06624         *funcid = InvalidOid;
06625     }
06626     else
06627     {
06628         ret = find_coercion_pathway(targetTypeId, sourceTypeId,
06629                                     COERCION_IMPLICIT, funcid);
06630         if (ret == COERCION_PATH_NONE)
06631             /* A previously-relied-upon cast is now gone. */
06632             elog(ERROR, "could not find cast from %u to %u",
06633                  sourceTypeId, targetTypeId);
06634     }
06635 
06636     return ret;
06637 }
06638 
06639 /* Permissions checks for ADD FOREIGN KEY */
06640 static void
06641 checkFkeyPermissions(Relation rel, int16 *attnums, int natts)
06642 {
06643     Oid         roleid = GetUserId();
06644     AclResult   aclresult;
06645     int         i;
06646 
06647     /* Okay if we have relation-level REFERENCES permission */
06648     aclresult = pg_class_aclcheck(RelationGetRelid(rel), roleid,
06649                                   ACL_REFERENCES);
06650     if (aclresult == ACLCHECK_OK)
06651         return;
06652     /* Else we must have REFERENCES on each column */
06653     for (i = 0; i < natts; i++)
06654     {
06655         aclresult = pg_attribute_aclcheck(RelationGetRelid(rel), attnums[i],
06656                                           roleid, ACL_REFERENCES);
06657         if (aclresult != ACLCHECK_OK)
06658             aclcheck_error(aclresult, ACL_KIND_CLASS,
06659                            RelationGetRelationName(rel));
06660     }
06661 }
06662 
06663 /*
06664  * Scan the existing rows in a table to verify they meet a proposed
06665  * CHECK constraint.
06666  *
06667  * The caller must have opened and locked the relation appropriately.
06668  */
06669 static void
06670 validateCheckConstraint(Relation rel, HeapTuple constrtup)
06671 {
06672     EState     *estate;
06673     Datum       val;
06674     char       *conbin;
06675     Expr       *origexpr;
06676     List       *exprstate;
06677     TupleDesc   tupdesc;
06678     HeapScanDesc scan;
06679     HeapTuple   tuple;
06680     ExprContext *econtext;
06681     MemoryContext oldcxt;
06682     TupleTableSlot *slot;
06683     Form_pg_constraint constrForm;
06684     bool        isnull;
06685 
06686     constrForm = (Form_pg_constraint) GETSTRUCT(constrtup);
06687 
06688     estate = CreateExecutorState();
06689 
06690     /*
06691      * XXX this tuple doesn't really come from a syscache, but this doesn't
06692      * matter to SysCacheGetAttr, because it only wants to be able to fetch
06693      * the tupdesc
06694      */
06695     val = SysCacheGetAttr(CONSTROID, constrtup, Anum_pg_constraint_conbin,
06696                           &isnull);
06697     if (isnull)
06698         elog(ERROR, "null conbin for constraint %u",
06699              HeapTupleGetOid(constrtup));
06700     conbin = TextDatumGetCString(val);
06701     origexpr = (Expr *) stringToNode(conbin);
06702     exprstate = (List *)
06703         ExecPrepareExpr((Expr *) make_ands_implicit(origexpr), estate);
06704 
06705     econtext = GetPerTupleExprContext(estate);
06706     tupdesc = RelationGetDescr(rel);
06707     slot = MakeSingleTupleTableSlot(tupdesc);
06708     econtext->ecxt_scantuple = slot;
06709 
06710     scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
06711 
06712     /*
06713      * Switch to per-tuple memory context and reset it for each tuple
06714      * produced, so we don't leak memory.
06715      */
06716     oldcxt = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
06717 
06718     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
06719     {
06720         ExecStoreTuple(tuple, slot, InvalidBuffer, false);
06721 
06722         if (!ExecQual(exprstate, econtext, true))
06723             ereport(ERROR,
06724                     (errcode(ERRCODE_CHECK_VIOLATION),
06725                      errmsg("check constraint \"%s\" is violated by some row",
06726                             NameStr(constrForm->conname)),
06727                      errtableconstraint(rel, NameStr(constrForm->conname))));
06728 
06729         ResetExprContext(econtext);
06730     }
06731 
06732     MemoryContextSwitchTo(oldcxt);
06733     heap_endscan(scan);
06734     ExecDropSingleTupleTableSlot(slot);
06735     FreeExecutorState(estate);
06736 }
06737 
06738 /*
06739  * Scan the existing rows in a table to verify they meet a proposed FK
06740  * constraint.
06741  *
06742  * Caller must have opened and locked both relations appropriately.
06743  */
06744 static void
06745 validateForeignKeyConstraint(char *conname,
06746                              Relation rel,
06747                              Relation pkrel,
06748                              Oid pkindOid,
06749                              Oid constraintOid)
06750 {
06751     HeapScanDesc scan;
06752     HeapTuple   tuple;
06753     Trigger     trig;
06754 
06755     ereport(DEBUG1,
06756             (errmsg("validating foreign key constraint \"%s\"", conname)));
06757 
06758     /*
06759      * Build a trigger call structure; we'll need it either way.
06760      */
06761     MemSet(&trig, 0, sizeof(trig));
06762     trig.tgoid = InvalidOid;
06763     trig.tgname = conname;
06764     trig.tgenabled = TRIGGER_FIRES_ON_ORIGIN;
06765     trig.tgisinternal = TRUE;
06766     trig.tgconstrrelid = RelationGetRelid(pkrel);
06767     trig.tgconstrindid = pkindOid;
06768     trig.tgconstraint = constraintOid;
06769     trig.tgdeferrable = FALSE;
06770     trig.tginitdeferred = FALSE;
06771     /* we needn't fill in tgargs or tgqual */
06772 
06773     /*
06774      * See if we can do it with a single LEFT JOIN query.  A FALSE result
06775      * indicates we must proceed with the fire-the-trigger method.
06776      */
06777     if (RI_Initial_Check(&trig, rel, pkrel))
06778         return;
06779 
06780     /*
06781      * Scan through each tuple, calling RI_FKey_check_ins (insert trigger) as
06782      * if that tuple had just been inserted.  If any of those fail, it should
06783      * ereport(ERROR) and that's that.
06784      */
06785     scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
06786 
06787     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
06788     {
06789         FunctionCallInfoData fcinfo;
06790         TriggerData trigdata;
06791 
06792         /*
06793          * Make a call to the trigger function
06794          *
06795          * No parameters are passed, but we do set a context
06796          */
06797         MemSet(&fcinfo, 0, sizeof(fcinfo));
06798 
06799         /*
06800          * We assume RI_FKey_check_ins won't look at flinfo...
06801          */
06802         trigdata.type = T_TriggerData;
06803         trigdata.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW;
06804         trigdata.tg_relation = rel;
06805         trigdata.tg_trigtuple = tuple;
06806         trigdata.tg_newtuple = NULL;
06807         trigdata.tg_trigger = &trig;
06808         trigdata.tg_trigtuplebuf = scan->rs_cbuf;
06809         trigdata.tg_newtuplebuf = InvalidBuffer;
06810 
06811         fcinfo.context = (Node *) &trigdata;
06812 
06813         RI_FKey_check_ins(&fcinfo);
06814     }
06815 
06816     heap_endscan(scan);
06817 }
06818 
06819 static void
06820 CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint,
06821                      Oid constraintOid, Oid indexOid, bool on_insert)
06822 {
06823     CreateTrigStmt *fk_trigger;
06824 
06825     /*
06826      * Note: for a self-referential FK (referencing and referenced tables are
06827      * the same), it is important that the ON UPDATE action fires before the
06828      * CHECK action, since both triggers will fire on the same row during an
06829      * UPDATE event; otherwise the CHECK trigger will be checking a non-final
06830      * state of the row.  Triggers fire in name order, so we ensure this by
06831      * using names like "RI_ConstraintTrigger_a_NNNN" for the action triggers
06832      * and "RI_ConstraintTrigger_c_NNNN" for the check triggers.
06833      */
06834     fk_trigger = makeNode(CreateTrigStmt);
06835     fk_trigger->trigname = "RI_ConstraintTrigger_c";
06836     fk_trigger->relation = myRel;
06837     fk_trigger->row = true;
06838     fk_trigger->timing = TRIGGER_TYPE_AFTER;
06839 
06840     /* Either ON INSERT or ON UPDATE */
06841     if (on_insert)
06842     {
06843         fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins");
06844         fk_trigger->events = TRIGGER_TYPE_INSERT;
06845     }
06846     else
06847     {
06848         fk_trigger->funcname = SystemFuncName("RI_FKey_check_upd");
06849         fk_trigger->events = TRIGGER_TYPE_UPDATE;
06850     }
06851 
06852     fk_trigger->columns = NIL;
06853     fk_trigger->whenClause = NULL;
06854     fk_trigger->isconstraint = true;
06855     fk_trigger->deferrable = fkconstraint->deferrable;
06856     fk_trigger->initdeferred = fkconstraint->initdeferred;
06857     fk_trigger->constrrel = fkconstraint->pktable;
06858     fk_trigger->args = NIL;
06859 
06860     (void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, true);
06861 
06862     /* Make changes-so-far visible */
06863     CommandCounterIncrement();
06864 }
06865 
06866 /*
06867  * Create the triggers that implement an FK constraint.
06868  */
06869 static void
06870 createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
06871                          Oid constraintOid, Oid indexOid)
06872 {
06873     RangeVar   *myRel;
06874     CreateTrigStmt *fk_trigger;
06875 
06876     /*
06877      * Reconstruct a RangeVar for my relation (not passed in, unfortunately).
06878      */
06879     myRel = makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
06880                          pstrdup(RelationGetRelationName(rel)),
06881                          -1);
06882 
06883     /* Make changes-so-far visible */
06884     CommandCounterIncrement();
06885 
06886     /*
06887      * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
06888      * DELETE action on the referenced table.
06889      */
06890     fk_trigger = makeNode(CreateTrigStmt);
06891     fk_trigger->trigname = "RI_ConstraintTrigger_a";
06892     fk_trigger->relation = fkconstraint->pktable;
06893     fk_trigger->row = true;
06894     fk_trigger->timing = TRIGGER_TYPE_AFTER;
06895     fk_trigger->events = TRIGGER_TYPE_DELETE;
06896     fk_trigger->columns = NIL;
06897     fk_trigger->whenClause = NULL;
06898     fk_trigger->isconstraint = true;
06899     fk_trigger->constrrel = myRel;
06900     switch (fkconstraint->fk_del_action)
06901     {
06902         case FKCONSTR_ACTION_NOACTION:
06903             fk_trigger->deferrable = fkconstraint->deferrable;
06904             fk_trigger->initdeferred = fkconstraint->initdeferred;
06905             fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_del");
06906             break;
06907         case FKCONSTR_ACTION_RESTRICT:
06908             fk_trigger->deferrable = false;
06909             fk_trigger->initdeferred = false;
06910             fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_del");
06911             break;
06912         case FKCONSTR_ACTION_CASCADE:
06913             fk_trigger->deferrable = false;
06914             fk_trigger->initdeferred = false;
06915             fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_del");
06916             break;
06917         case FKCONSTR_ACTION_SETNULL:
06918             fk_trigger->deferrable = false;
06919             fk_trigger->initdeferred = false;
06920             fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_del");
06921             break;
06922         case FKCONSTR_ACTION_SETDEFAULT:
06923             fk_trigger->deferrable = false;
06924             fk_trigger->initdeferred = false;
06925             fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_del");
06926             break;
06927         default:
06928             elog(ERROR, "unrecognized FK action type: %d",
06929                  (int) fkconstraint->fk_del_action);
06930             break;
06931     }
06932     fk_trigger->args = NIL;
06933 
06934     (void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, true);
06935 
06936     /* Make changes-so-far visible */
06937     CommandCounterIncrement();
06938 
06939     /*
06940      * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON
06941      * UPDATE action on the referenced table.
06942      */
06943     fk_trigger = makeNode(CreateTrigStmt);
06944     fk_trigger->trigname = "RI_ConstraintTrigger_a";
06945     fk_trigger->relation = fkconstraint->pktable;
06946     fk_trigger->row = true;
06947     fk_trigger->timing = TRIGGER_TYPE_AFTER;
06948     fk_trigger->events = TRIGGER_TYPE_UPDATE;
06949     fk_trigger->columns = NIL;
06950     fk_trigger->whenClause = NULL;
06951     fk_trigger->isconstraint = true;
06952     fk_trigger->constrrel = myRel;
06953     switch (fkconstraint->fk_upd_action)
06954     {
06955         case FKCONSTR_ACTION_NOACTION:
06956             fk_trigger->deferrable = fkconstraint->deferrable;
06957             fk_trigger->initdeferred = fkconstraint->initdeferred;
06958             fk_trigger->funcname = SystemFuncName("RI_FKey_noaction_upd");
06959             break;
06960         case FKCONSTR_ACTION_RESTRICT:
06961             fk_trigger->deferrable = false;
06962             fk_trigger->initdeferred = false;
06963             fk_trigger->funcname = SystemFuncName("RI_FKey_restrict_upd");
06964             break;
06965         case FKCONSTR_ACTION_CASCADE:
06966             fk_trigger->deferrable = false;
06967             fk_trigger->initdeferred = false;
06968             fk_trigger->funcname = SystemFuncName("RI_FKey_cascade_upd");
06969             break;
06970         case FKCONSTR_ACTION_SETNULL:
06971             fk_trigger->deferrable = false;
06972             fk_trigger->initdeferred = false;
06973             fk_trigger->funcname = SystemFuncName("RI_FKey_setnull_upd");
06974             break;
06975         case FKCONSTR_ACTION_SETDEFAULT:
06976             fk_trigger->deferrable = false;
06977             fk_trigger->initdeferred = false;
06978             fk_trigger->funcname = SystemFuncName("RI_FKey_setdefault_upd");
06979             break;
06980         default:
06981             elog(ERROR, "unrecognized FK action type: %d",
06982                  (int) fkconstraint->fk_upd_action);
06983             break;
06984     }
06985     fk_trigger->args = NIL;
06986 
06987     (void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, true);
06988 
06989     /* Make changes-so-far visible */
06990     CommandCounterIncrement();
06991 
06992     /*
06993      * Build and execute CREATE CONSTRAINT TRIGGER statements for the CHECK
06994      * action for both INSERTs and UPDATEs on the referencing table.
06995      */
06996     CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, indexOid, true);
06997     CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, indexOid, false);
06998 }
06999 
07000 /*
07001  * ALTER TABLE DROP CONSTRAINT
07002  *
07003  * Like DROP COLUMN, we can't use the normal ALTER TABLE recursion mechanism.
07004  */
07005 static void
07006 ATExecDropConstraint(Relation rel, const char *constrName,
07007                      DropBehavior behavior,
07008                      bool recurse, bool recursing,
07009                      bool missing_ok, LOCKMODE lockmode)
07010 {
07011     List       *children;
07012     ListCell   *child;
07013     Relation    conrel;
07014     Form_pg_constraint con;
07015     SysScanDesc scan;
07016     ScanKeyData key;
07017     HeapTuple   tuple;
07018     bool        found = false;
07019     bool        is_no_inherit_constraint = false;
07020 
07021     /* At top level, permission check was done in ATPrepCmd, else do it */
07022     if (recursing)
07023         ATSimplePermissions(rel, ATT_TABLE);
07024 
07025     conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
07026 
07027     /*
07028      * Find and drop the target constraint
07029      */
07030     ScanKeyInit(&key,
07031                 Anum_pg_constraint_conrelid,
07032                 BTEqualStrategyNumber, F_OIDEQ,
07033                 ObjectIdGetDatum(RelationGetRelid(rel)));
07034     scan = systable_beginscan(conrel, ConstraintRelidIndexId,
07035                               true, SnapshotNow, 1, &key);
07036 
07037     while (HeapTupleIsValid(tuple = systable_getnext(scan)))
07038     {
07039         ObjectAddress conobj;
07040 
07041         con = (Form_pg_constraint) GETSTRUCT(tuple);
07042 
07043         if (strcmp(NameStr(con->conname), constrName) != 0)
07044             continue;
07045 
07046         /* Don't drop inherited constraints */
07047         if (con->coninhcount > 0 && !recursing)
07048             ereport(ERROR,
07049                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
07050                      errmsg("cannot drop inherited constraint \"%s\" of relation \"%s\"",
07051                             constrName, RelationGetRelationName(rel))));
07052 
07053         is_no_inherit_constraint = con->connoinherit;
07054 
07055         /*
07056          * Perform the actual constraint deletion
07057          */
07058         conobj.classId = ConstraintRelationId;
07059         conobj.objectId = HeapTupleGetOid(tuple);
07060         conobj.objectSubId = 0;
07061 
07062         performDeletion(&conobj, behavior, 0);
07063 
07064         found = true;
07065 
07066         /* constraint found and dropped -- no need to keep looping */
07067         break;
07068     }
07069 
07070     systable_endscan(scan);
07071 
07072     if (!found)
07073     {
07074         if (!missing_ok)
07075         {
07076             ereport(ERROR,
07077                     (errcode(ERRCODE_UNDEFINED_OBJECT),
07078                 errmsg("constraint \"%s\" of relation \"%s\" does not exist",
07079                        constrName, RelationGetRelationName(rel))));
07080         }
07081         else
07082         {
07083             ereport(NOTICE,
07084                     (errmsg("constraint \"%s\" of relation \"%s\" does not exist, skipping",
07085                             constrName, RelationGetRelationName(rel))));
07086             heap_close(conrel, RowExclusiveLock);
07087             return;
07088         }
07089     }
07090 
07091     /*
07092      * Propagate to children as appropriate.  Unlike most other ALTER
07093      * routines, we have to do this one level of recursion at a time; we can't
07094      * use find_all_inheritors to do it in one pass.
07095      */
07096     if (!is_no_inherit_constraint)
07097         children = find_inheritance_children(RelationGetRelid(rel), lockmode);
07098     else
07099         children = NIL;
07100 
07101     foreach(child, children)
07102     {
07103         Oid         childrelid = lfirst_oid(child);
07104         Relation    childrel;
07105         HeapTuple   copy_tuple;
07106 
07107         /* find_inheritance_children already got lock */
07108         childrel = heap_open(childrelid, NoLock);
07109         CheckTableNotInUse(childrel, "ALTER TABLE");
07110 
07111         ScanKeyInit(&key,
07112                     Anum_pg_constraint_conrelid,
07113                     BTEqualStrategyNumber, F_OIDEQ,
07114                     ObjectIdGetDatum(childrelid));
07115         scan = systable_beginscan(conrel, ConstraintRelidIndexId,
07116                                   true, SnapshotNow, 1, &key);
07117 
07118         /* scan for matching tuple - there should only be one */
07119         while (HeapTupleIsValid(tuple = systable_getnext(scan)))
07120         {
07121             con = (Form_pg_constraint) GETSTRUCT(tuple);
07122 
07123             /* Right now only CHECK constraints can be inherited */
07124             if (con->contype != CONSTRAINT_CHECK)
07125                 continue;
07126 
07127             if (strcmp(NameStr(con->conname), constrName) == 0)
07128                 break;
07129         }
07130 
07131         if (!HeapTupleIsValid(tuple))
07132             ereport(ERROR,
07133                     (errcode(ERRCODE_UNDEFINED_OBJECT),
07134                 errmsg("constraint \"%s\" of relation \"%s\" does not exist",
07135                        constrName,
07136                        RelationGetRelationName(childrel))));
07137 
07138         copy_tuple = heap_copytuple(tuple);
07139 
07140         systable_endscan(scan);
07141 
07142         con = (Form_pg_constraint) GETSTRUCT(copy_tuple);
07143 
07144         if (con->coninhcount <= 0)      /* shouldn't happen */
07145             elog(ERROR, "relation %u has non-inherited constraint \"%s\"",
07146                  childrelid, constrName);
07147 
07148         if (recurse)
07149         {
07150             /*
07151              * If the child constraint has other definition sources, just
07152              * decrement its inheritance count; if not, recurse to delete it.
07153              */
07154             if (con->coninhcount == 1 && !con->conislocal)
07155             {
07156                 /* Time to delete this child constraint, too */
07157                 ATExecDropConstraint(childrel, constrName, behavior,
07158                                      true, true,
07159                                      false, lockmode);
07160             }
07161             else
07162             {
07163                 /* Child constraint must survive my deletion */
07164                 con->coninhcount--;
07165                 simple_heap_update(conrel, &copy_tuple->t_self, copy_tuple);
07166                 CatalogUpdateIndexes(conrel, copy_tuple);
07167 
07168                 /* Make update visible */
07169                 CommandCounterIncrement();
07170             }
07171         }
07172         else
07173         {
07174             /*
07175              * If we were told to drop ONLY in this table (no recursion), we
07176              * need to mark the inheritors' constraints as locally defined
07177              * rather than inherited.
07178              */
07179             con->coninhcount--;
07180             con->conislocal = true;
07181 
07182             simple_heap_update(conrel, &copy_tuple->t_self, copy_tuple);
07183             CatalogUpdateIndexes(conrel, copy_tuple);
07184 
07185             /* Make update visible */
07186             CommandCounterIncrement();
07187         }
07188 
07189         heap_freetuple(copy_tuple);
07190 
07191         heap_close(childrel, NoLock);
07192     }
07193 
07194     heap_close(conrel, RowExclusiveLock);
07195 }
07196 
07197 /*
07198  * ALTER COLUMN TYPE
07199  */
07200 static void
07201 ATPrepAlterColumnType(List **wqueue,
07202                       AlteredTableInfo *tab, Relation rel,
07203                       bool recurse, bool recursing,
07204                       AlterTableCmd *cmd, LOCKMODE lockmode)
07205 {
07206     char       *colName = cmd->name;
07207     ColumnDef  *def = (ColumnDef *) cmd->def;
07208     TypeName   *typeName = def->typeName;
07209     Node       *transform = def->raw_default;
07210     HeapTuple   tuple;
07211     Form_pg_attribute attTup;
07212     AttrNumber  attnum;
07213     Oid         targettype;
07214     int32       targettypmod;
07215     Oid         targetcollid;
07216     NewColumnValue *newval;
07217     ParseState *pstate = make_parsestate(NULL);
07218     AclResult   aclresult;
07219 
07220     if (rel->rd_rel->reloftype && !recursing)
07221         ereport(ERROR,
07222                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
07223                  errmsg("cannot alter column type of typed table")));
07224 
07225     /* lookup the attribute so we can check inheritance status */
07226     tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
07227     if (!HeapTupleIsValid(tuple))
07228         ereport(ERROR,
07229                 (errcode(ERRCODE_UNDEFINED_COLUMN),
07230                  errmsg("column \"%s\" of relation \"%s\" does not exist",
07231                         colName, RelationGetRelationName(rel))));
07232     attTup = (Form_pg_attribute) GETSTRUCT(tuple);
07233     attnum = attTup->attnum;
07234 
07235     /* Can't alter a system attribute */
07236     if (attnum <= 0)
07237         ereport(ERROR,
07238                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
07239                  errmsg("cannot alter system column \"%s\"",
07240                         colName)));
07241 
07242     /* Don't alter inherited columns */
07243     if (attTup->attinhcount > 0 && !recursing)
07244         ereport(ERROR,
07245                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
07246                  errmsg("cannot alter inherited column \"%s\"",
07247                         colName)));
07248 
07249     /* Look up the target type */
07250     typenameTypeIdAndMod(NULL, typeName, &targettype, &targettypmod);
07251 
07252     aclresult = pg_type_aclcheck(targettype, GetUserId(), ACL_USAGE);
07253     if (aclresult != ACLCHECK_OK)
07254         aclcheck_error_type(aclresult, targettype);
07255 
07256     /* And the collation */
07257     targetcollid = GetColumnDefCollation(NULL, def, targettype);
07258 
07259     /* make sure datatype is legal for a column */
07260     CheckAttributeType(colName, targettype, targetcollid,
07261                        list_make1_oid(rel->rd_rel->reltype),
07262                        false);
07263 
07264     if (tab->relkind == RELKIND_RELATION)
07265     {
07266         /*
07267          * Set up an expression to transform the old data value to the new
07268          * type. If a USING option was given, transform and use that
07269          * expression, else just take the old value and try to coerce it.  We
07270          * do this first so that type incompatibility can be detected before
07271          * we waste effort, and because we need the expression to be parsed
07272          * against the original table row type.
07273          */
07274         if (transform)
07275         {
07276             RangeTblEntry *rte;
07277 
07278             /* Expression must be able to access vars of old table */
07279             rte = addRangeTableEntryForRelation(pstate,
07280                                                 rel,
07281                                                 NULL,
07282                                                 false,
07283                                                 true);
07284             addRTEtoQuery(pstate, rte, false, true, true);
07285 
07286             transform = transformExpr(pstate, transform,
07287                                       EXPR_KIND_ALTER_COL_TRANSFORM);
07288 
07289             /* It can't return a set */
07290             if (expression_returns_set(transform))
07291                 ereport(ERROR,
07292                         (errcode(ERRCODE_DATATYPE_MISMATCH),
07293                       errmsg("transform expression must not return a set")));
07294         }
07295         else
07296         {
07297             transform = (Node *) makeVar(1, attnum,
07298                                          attTup->atttypid, attTup->atttypmod,
07299                                          attTup->attcollation,
07300                                          0);
07301         }
07302 
07303         transform = coerce_to_target_type(pstate,
07304                                           transform, exprType(transform),
07305                                           targettype, targettypmod,
07306                                           COERCION_ASSIGNMENT,
07307                                           COERCE_IMPLICIT_CAST,
07308                                           -1);
07309         if (transform == NULL)
07310             ereport(ERROR,
07311                     (errcode(ERRCODE_DATATYPE_MISMATCH),
07312               errmsg("column \"%s\" cannot be cast automatically to type %s",
07313                      colName, format_type_be(targettype)),
07314                      errhint("Specify a USING expression to perform the conversion.")));
07315 
07316         /* Fix collations after all else */
07317         assign_expr_collations(pstate, transform);
07318 
07319         /* Plan the expr now so we can accurately assess the need to rewrite. */
07320         transform = (Node *) expression_planner((Expr *) transform);
07321 
07322         /*
07323          * Add a work queue item to make ATRewriteTable update the column
07324          * contents.
07325          */
07326         newval = (NewColumnValue *) palloc0(sizeof(NewColumnValue));
07327         newval->attnum = attnum;
07328         newval->expr = (Expr *) transform;
07329 
07330         tab->newvals = lappend(tab->newvals, newval);
07331         if (ATColumnChangeRequiresRewrite(transform, attnum))
07332             tab->rewrite = true;
07333     }
07334     else if (transform)
07335         ereport(ERROR,
07336                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
07337                  errmsg("\"%s\" is not a table",
07338                         RelationGetRelationName(rel))));
07339 
07340     if (tab->relkind == RELKIND_COMPOSITE_TYPE ||
07341         tab->relkind == RELKIND_FOREIGN_TABLE)
07342     {
07343         /*
07344          * For composite types, do this check now.  Tables will check it later
07345          * when the table is being rewritten.
07346          */
07347         find_composite_type_dependencies(rel->rd_rel->reltype, rel, NULL);
07348     }
07349 
07350     ReleaseSysCache(tuple);
07351 
07352     /*
07353      * The recursion case is handled by ATSimpleRecursion.  However, if we are
07354      * told not to recurse, there had better not be any child tables; else the
07355      * alter would put them out of step.
07356      */
07357     if (recurse)
07358         ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode);
07359     else if (!recursing &&
07360              find_inheritance_children(RelationGetRelid(rel), NoLock) != NIL)
07361         ereport(ERROR,
07362                 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
07363                  errmsg("type of inherited column \"%s\" must be changed in child tables too",
07364                         colName)));
07365 
07366     if (tab->relkind == RELKIND_COMPOSITE_TYPE)
07367         ATTypedTableRecursion(wqueue, rel, cmd, lockmode);
07368 }
07369 
07370 /*
07371  * When the data type of a column is changed, a rewrite might not be required
07372  * if the new type is sufficiently identical to the old one, and the USING
07373  * clause isn't trying to insert some other value.  It's safe to skip the
07374  * rewrite if the old type is binary coercible to the new type, or if the
07375  * new type is an unconstrained domain over the old type.  In the case of a
07376  * constrained domain, we could get by with scanning the table and checking
07377  * the constraint rather than actually rewriting it, but we don't currently
07378  * try to do that.
07379  */
07380 static bool
07381 ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno)
07382 {
07383     Assert(expr != NULL);
07384 
07385     for (;;)
07386     {
07387         /* only one varno, so no need to check that */
07388         if (IsA(expr, Var) &&((Var *) expr)->varattno == varattno)
07389             return false;
07390         else if (IsA(expr, RelabelType))
07391             expr = (Node *) ((RelabelType *) expr)->arg;
07392         else if (IsA(expr, CoerceToDomain))
07393         {
07394             CoerceToDomain *d = (CoerceToDomain *) expr;
07395 
07396             if (GetDomainConstraints(d->resulttype) != NIL)
07397                 return true;
07398             expr = (Node *) d->arg;
07399         }
07400         else
07401             return true;
07402     }
07403 }
07404 
07405 static void
07406 ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
07407                       AlterTableCmd *cmd, LOCKMODE lockmode)
07408 {
07409     char       *colName = cmd->name;
07410     ColumnDef  *def = (ColumnDef *) cmd->def;
07411     TypeName   *typeName = def->typeName;
07412     HeapTuple   heapTup;
07413     Form_pg_attribute attTup;
07414     AttrNumber  attnum;
07415     HeapTuple   typeTuple;
07416     Form_pg_type tform;
07417     Oid         targettype;
07418     int32       targettypmod;
07419     Oid         targetcollid;
07420     Node       *defaultexpr;
07421     Relation    attrelation;
07422     Relation    depRel;
07423     ScanKeyData key[3];
07424     SysScanDesc scan;
07425     HeapTuple   depTup;
07426 
07427     attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
07428 
07429     /* Look up the target column */
07430     heapTup = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName);
07431     if (!HeapTupleIsValid(heapTup))     /* shouldn't happen */
07432         ereport(ERROR,
07433                 (errcode(ERRCODE_UNDEFINED_COLUMN),
07434                  errmsg("column \"%s\" of relation \"%s\" does not exist",
07435                         colName, RelationGetRelationName(rel))));
07436     attTup = (Form_pg_attribute) GETSTRUCT(heapTup);
07437     attnum = attTup->attnum;
07438 
07439     /* Check for multiple ALTER TYPE on same column --- can't cope */
07440     if (attTup->atttypid != tab->oldDesc->attrs[attnum - 1]->atttypid ||
07441         attTup->atttypmod != tab->oldDesc->attrs[attnum - 1]->atttypmod)
07442         ereport(ERROR,
07443                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
07444                  errmsg("cannot alter type of column \"%s\" twice",
07445                         colName)));
07446 
07447     /* Look up the target type (should not fail, since prep found it) */
07448     typeTuple = typenameType(NULL, typeName, &targettypmod);
07449     tform = (Form_pg_type) GETSTRUCT(typeTuple);
07450     targettype = HeapTupleGetOid(typeTuple);
07451     /* And the collation */
07452     targetcollid = GetColumnDefCollation(NULL, def, targettype);
07453 
07454     /*
07455      * If there is a default expression for the column, get it and ensure we
07456      * can coerce it to the new datatype.  (We must do this before changing
07457      * the column type, because build_column_default itself will try to
07458      * coerce, and will not issue the error message we want if it fails.)
07459      *
07460      * We remove any implicit coercion steps at the top level of the old
07461      * default expression; this has been agreed to satisfy the principle of
07462      * least surprise.  (The conversion to the new column type should act like
07463      * it started from what the user sees as the stored expression, and the
07464      * implicit coercions aren't going to be shown.)
07465      */
07466     if (attTup->atthasdef)
07467     {
07468         defaultexpr = build_column_default(rel, attnum);
07469         Assert(defaultexpr);
07470         defaultexpr = strip_implicit_coercions(defaultexpr);
07471         defaultexpr = coerce_to_target_type(NULL,       /* no UNKNOWN params */
07472                                           defaultexpr, exprType(defaultexpr),
07473                                             targettype, targettypmod,
07474                                             COERCION_ASSIGNMENT,
07475                                             COERCE_IMPLICIT_CAST,
07476                                             -1);
07477         if (defaultexpr == NULL)
07478             ereport(ERROR,
07479                     (errcode(ERRCODE_DATATYPE_MISMATCH),
07480                      errmsg("default for column \"%s\" cannot be cast automatically to type %s",
07481                             colName, format_type_be(targettype))));
07482     }
07483     else
07484         defaultexpr = NULL;
07485 
07486     /*
07487      * Find everything that depends on the column (constraints, indexes, etc),
07488      * and record enough information to let us recreate the objects.
07489      *
07490      * The actual recreation does not happen here, but only after we have
07491      * performed all the individual ALTER TYPE operations.  We have to save
07492      * the info before executing ALTER TYPE, though, else the deparser will
07493      * get confused.
07494      *
07495      * There could be multiple entries for the same object, so we must check
07496      * to ensure we process each one only once.  Note: we assume that an index
07497      * that implements a constraint will not show a direct dependency on the
07498      * column.
07499      */
07500     depRel = heap_open(DependRelationId, RowExclusiveLock);
07501 
07502     ScanKeyInit(&key[0],
07503                 Anum_pg_depend_refclassid,
07504                 BTEqualStrategyNumber, F_OIDEQ,
07505                 ObjectIdGetDatum(RelationRelationId));
07506     ScanKeyInit(&key[1],
07507                 Anum_pg_depend_refobjid,
07508                 BTEqualStrategyNumber, F_OIDEQ,
07509                 ObjectIdGetDatum(RelationGetRelid(rel)));
07510     ScanKeyInit(&key[2],
07511                 Anum_pg_depend_refobjsubid,
07512                 BTEqualStrategyNumber, F_INT4EQ,
07513                 Int32GetDatum((int32) attnum));
07514 
07515     scan = systable_beginscan(depRel, DependReferenceIndexId, true,
07516                               SnapshotNow, 3, key);
07517 
07518     while (HeapTupleIsValid(depTup = systable_getnext(scan)))
07519     {
07520         Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(depTup);
07521         ObjectAddress foundObject;
07522 
07523         /* We don't expect any PIN dependencies on columns */
07524         if (foundDep->deptype == DEPENDENCY_PIN)
07525             elog(ERROR, "cannot alter type of a pinned column");
07526 
07527         foundObject.classId = foundDep->classid;
07528         foundObject.objectId = foundDep->objid;
07529         foundObject.objectSubId = foundDep->objsubid;
07530 
07531         switch (getObjectClass(&foundObject))
07532         {
07533             case OCLASS_CLASS:
07534                 {
07535                     char        relKind = get_rel_relkind(foundObject.objectId);
07536 
07537                     if (relKind == RELKIND_INDEX)
07538                     {
07539                         Assert(foundObject.objectSubId == 0);
07540                         if (!list_member_oid(tab->changedIndexOids, foundObject.objectId))
07541                         {
07542                             tab->changedIndexOids = lappend_oid(tab->changedIndexOids,
07543                                                        foundObject.objectId);
07544                             tab->changedIndexDefs = lappend(tab->changedIndexDefs,
07545                                pg_get_indexdef_string(foundObject.objectId));
07546                         }
07547                     }
07548                     else if (relKind == RELKIND_SEQUENCE)
07549                     {
07550                         /*
07551                          * This must be a SERIAL column's sequence.  We need
07552                          * not do anything to it.
07553                          */
07554                         Assert(foundObject.objectSubId == 0);
07555                     }
07556                     else
07557                     {
07558                         /* Not expecting any other direct dependencies... */
07559                         elog(ERROR, "unexpected object depending on column: %s",
07560                              getObjectDescription(&foundObject));
07561                     }
07562                     break;
07563                 }
07564 
07565             case OCLASS_CONSTRAINT:
07566                 Assert(foundObject.objectSubId == 0);
07567                 if (!list_member_oid(tab->changedConstraintOids,
07568                                      foundObject.objectId))
07569                 {
07570                     char       *defstring = pg_get_constraintdef_string(foundObject.objectId);
07571 
07572                     /*
07573                      * Put NORMAL dependencies at the front of the list and
07574                      * AUTO dependencies at the back.  This makes sure that
07575                      * foreign-key constraints depending on this column will
07576                      * be dropped before unique or primary-key constraints of
07577                      * the column; which we must have because the FK
07578                      * constraints depend on the indexes belonging to the
07579                      * unique constraints.
07580                      */
07581                     if (foundDep->deptype == DEPENDENCY_NORMAL)
07582                     {
07583                         tab->changedConstraintOids =
07584                             lcons_oid(foundObject.objectId,
07585                                       tab->changedConstraintOids);
07586                         tab->changedConstraintDefs =
07587                             lcons(defstring,
07588                                   tab->changedConstraintDefs);
07589                     }
07590                     else
07591                     {
07592                         tab->changedConstraintOids =
07593                             lappend_oid(tab->changedConstraintOids,
07594                                         foundObject.objectId);
07595                         tab->changedConstraintDefs =
07596                             lappend(tab->changedConstraintDefs,
07597                                     defstring);
07598                     }
07599                 }
07600                 break;
07601 
07602             case OCLASS_REWRITE:
07603                 /* XXX someday see if we can cope with revising views */
07604                 ereport(ERROR,
07605                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
07606                          errmsg("cannot alter type of a column used by a view or rule"),
07607                          errdetail("%s depends on column \"%s\"",
07608                                    getObjectDescription(&foundObject),
07609                                    colName)));
07610                 break;
07611 
07612             case OCLASS_TRIGGER:
07613 
07614                 /*
07615                  * A trigger can depend on a column because the column is
07616                  * specified as an update target, or because the column is
07617                  * used in the trigger's WHEN condition.  The first case would
07618                  * not require any extra work, but the second case would
07619                  * require updating the WHEN expression, which will take a
07620                  * significant amount of new code.  Since we can't easily tell
07621                  * which case applies, we punt for both.  FIXME someday.
07622                  */
07623                 ereport(ERROR,
07624                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
07625                          errmsg("cannot alter type of a column used in a trigger definition"),
07626                          errdetail("%s depends on column \"%s\"",
07627                                    getObjectDescription(&foundObject),
07628                                    colName)));
07629                 break;
07630 
07631             case OCLASS_DEFAULT:
07632 
07633                 /*
07634                  * Ignore the column's default expression, since we will fix
07635                  * it below.
07636                  */
07637                 Assert(defaultexpr);
07638                 break;
07639 
07640             case OCLASS_PROC:
07641             case OCLASS_TYPE:
07642             case OCLASS_CAST:
07643             case OCLASS_COLLATION:
07644             case OCLASS_CONVERSION:
07645             case OCLASS_LANGUAGE:
07646             case OCLASS_LARGEOBJECT:
07647             case OCLASS_OPERATOR:
07648             case OCLASS_OPCLASS:
07649             case OCLASS_OPFAMILY:
07650             case OCLASS_AMOP:
07651             case OCLASS_AMPROC:
07652             case OCLASS_SCHEMA:
07653             case OCLASS_TSPARSER:
07654             case OCLASS_TSDICT:
07655             case OCLASS_TSTEMPLATE:
07656             case OCLASS_TSCONFIG:
07657             case OCLASS_ROLE:
07658             case OCLASS_DATABASE:
07659             case OCLASS_TBLSPACE:
07660             case OCLASS_FDW:
07661             case OCLASS_FOREIGN_SERVER:
07662             case OCLASS_USER_MAPPING:
07663             case OCLASS_DEFACL:
07664             case OCLASS_EXTENSION:
07665 
07666                 /*
07667                  * We don't expect any of these sorts of objects to depend on
07668                  * a column.
07669                  */
07670                 elog(ERROR, "unexpected object depending on column: %s",
07671                      getObjectDescription(&foundObject));
07672                 break;
07673 
07674             default:
07675                 elog(ERROR, "unrecognized object class: %u",
07676                      foundObject.classId);
07677         }
07678     }
07679 
07680     systable_endscan(scan);
07681 
07682     /*
07683      * Now scan for dependencies of this column on other things.  The only
07684      * thing we should find is the dependency on the column datatype, which we
07685      * want to remove, and possibly a collation dependency.
07686      */
07687     ScanKeyInit(&key[0],
07688                 Anum_pg_depend_classid,
07689                 BTEqualStrategyNumber, F_OIDEQ,
07690                 ObjectIdGetDatum(RelationRelationId));
07691     ScanKeyInit(&key[1],
07692                 Anum_pg_depend_objid,
07693                 BTEqualStrategyNumber, F_OIDEQ,
07694                 ObjectIdGetDatum(RelationGetRelid(rel)));
07695     ScanKeyInit(&key[2],
07696                 Anum_pg_depend_objsubid,
07697                 BTEqualStrategyNumber, F_INT4EQ,
07698                 Int32GetDatum((int32) attnum));
07699 
07700     scan = systable_beginscan(depRel, DependDependerIndexId, true,
07701                               SnapshotNow, 3, key);
07702 
07703     while (HeapTupleIsValid(depTup = systable_getnext(scan)))
07704     {
07705         Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(depTup);
07706 
07707         if (foundDep->deptype != DEPENDENCY_NORMAL)
07708             elog(ERROR, "found unexpected dependency type '%c'",
07709                  foundDep->deptype);
07710         if (!(foundDep->refclassid == TypeRelationId &&
07711               foundDep->refobjid == attTup->atttypid) &&
07712             !(foundDep->refclassid == CollationRelationId &&
07713               foundDep->refobjid == attTup->attcollation))
07714             elog(ERROR, "found unexpected dependency for column");
07715 
07716         simple_heap_delete(depRel, &depTup->t_self);
07717     }
07718 
07719     systable_endscan(scan);
07720 
07721     heap_close(depRel, RowExclusiveLock);
07722 
07723     /*
07724      * Here we go --- change the recorded column type and collation.  (Note
07725      * heapTup is a copy of the syscache entry, so okay to scribble on.)
07726      */
07727     attTup->atttypid = targettype;
07728     attTup->atttypmod = targettypmod;
07729     attTup->attcollation = targetcollid;
07730     attTup->attndims = list_length(typeName->arrayBounds);
07731     attTup->attlen = tform->typlen;
07732     attTup->attbyval = tform->typbyval;
07733     attTup->attalign = tform->typalign;
07734     attTup->attstorage = tform->typstorage;
07735 
07736     ReleaseSysCache(typeTuple);
07737 
07738     simple_heap_update(attrelation, &heapTup->t_self, heapTup);
07739 
07740     /* keep system catalog indexes current */
07741     CatalogUpdateIndexes(attrelation, heapTup);
07742 
07743     heap_close(attrelation, RowExclusiveLock);
07744 
07745     /* Install dependencies on new datatype and collation */
07746     add_column_datatype_dependency(RelationGetRelid(rel), attnum, targettype);
07747     add_column_collation_dependency(RelationGetRelid(rel), attnum, targetcollid);
07748 
07749     /*
07750      * Drop any pg_statistic entry for the column, since it's now wrong type
07751      */
07752     RemoveStatistics(RelationGetRelid(rel), attnum);
07753 
07754     InvokeObjectPostAlterHook(RelationRelationId,
07755                               RelationGetRelid(rel), attnum);
07756 
07757     /*
07758      * Update the default, if present, by brute force --- remove and re-add
07759      * the default.  Probably unsafe to take shortcuts, since the new version
07760      * may well have additional dependencies.  (It's okay to do this now,
07761      * rather than after other ALTER TYPE commands, since the default won't
07762      * depend on other column types.)
07763      */
07764     if (defaultexpr)
07765     {
07766         /* Must make new row visible since it will be updated again */
07767         CommandCounterIncrement();
07768 
07769         /*
07770          * We use RESTRICT here for safety, but at present we do not expect
07771          * anything to depend on the default.
07772          */
07773         RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true,
07774                           true);
07775 
07776         StoreAttrDefault(rel, attnum, defaultexpr, true);
07777     }
07778 
07779     /* Cleanup */
07780     heap_freetuple(heapTup);
07781 }
07782 
07783 static void
07784 ATExecAlterColumnGenericOptions(Relation rel,
07785                                 const char *colName,
07786                                 List *options,
07787                                 LOCKMODE lockmode)
07788 {
07789     Relation    ftrel;
07790     Relation    attrel;
07791     ForeignServer *server;
07792     ForeignDataWrapper *fdw;
07793     HeapTuple   tuple;
07794     HeapTuple   newtuple;
07795     bool        isnull;
07796     Datum       repl_val[Natts_pg_attribute];
07797     bool        repl_null[Natts_pg_attribute];
07798     bool        repl_repl[Natts_pg_attribute];
07799     Datum       datum;
07800     Form_pg_foreign_table fttableform;
07801     Form_pg_attribute atttableform;
07802 
07803     if (options == NIL)
07804         return;
07805 
07806     /* First, determine FDW validator associated to the foreign table. */
07807     ftrel = heap_open(ForeignTableRelationId, AccessShareLock);
07808     tuple = SearchSysCache1(FOREIGNTABLEREL, rel->rd_id);
07809     if (!HeapTupleIsValid(tuple))
07810         ereport(ERROR,
07811                 (errcode(ERRCODE_UNDEFINED_OBJECT),
07812                  errmsg("foreign table \"%s\" does not exist",
07813                         RelationGetRelationName(rel))));
07814     fttableform = (Form_pg_foreign_table) GETSTRUCT(tuple);
07815     server = GetForeignServer(fttableform->ftserver);
07816     fdw = GetForeignDataWrapper(server->fdwid);
07817 
07818     heap_close(ftrel, AccessShareLock);
07819     ReleaseSysCache(tuple);
07820 
07821     attrel = heap_open(AttributeRelationId, RowExclusiveLock);
07822     tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName);
07823     if (!HeapTupleIsValid(tuple))
07824         ereport(ERROR,
07825                 (errcode(ERRCODE_UNDEFINED_COLUMN),
07826                  errmsg("column \"%s\" of relation \"%s\" does not exist",
07827                         colName, RelationGetRelationName(rel))));
07828 
07829     /* Prevent them from altering a system attribute */
07830     atttableform = (Form_pg_attribute) GETSTRUCT(tuple);
07831     if (atttableform->attnum <= 0)
07832         ereport(ERROR,
07833                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
07834                  errmsg("cannot alter system column \"%s\"", colName)));
07835 
07836 
07837     /* Initialize buffers for new tuple values */
07838     memset(repl_val, 0, sizeof(repl_val));
07839     memset(repl_null, false, sizeof(repl_null));
07840     memset(repl_repl, false, sizeof(repl_repl));
07841 
07842     /* Extract the current options */
07843     datum = SysCacheGetAttr(ATTNAME,
07844                             tuple,
07845                             Anum_pg_attribute_attfdwoptions,
07846                             &isnull);
07847     if (isnull)
07848         datum = PointerGetDatum(NULL);
07849 
07850     /* Transform the options */
07851     datum = transformGenericOptions(AttributeRelationId,
07852                                     datum,
07853                                     options,
07854                                     fdw->fdwvalidator);
07855 
07856     if (PointerIsValid(DatumGetPointer(datum)))
07857         repl_val[Anum_pg_attribute_attfdwoptions - 1] = datum;
07858     else
07859         repl_null[Anum_pg_attribute_attfdwoptions - 1] = true;
07860 
07861     repl_repl[Anum_pg_attribute_attfdwoptions - 1] = true;
07862 
07863     /* Everything looks good - update the tuple */
07864 
07865     newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrel),
07866                                  repl_val, repl_null, repl_repl);
07867 
07868     simple_heap_update(attrel, &newtuple->t_self, newtuple);
07869     CatalogUpdateIndexes(attrel, newtuple);
07870 
07871     InvokeObjectPostAlterHook(RelationRelationId,
07872                               RelationGetRelid(rel),
07873                               atttableform->attnum);
07874 
07875     ReleaseSysCache(tuple);
07876 
07877     heap_close(attrel, RowExclusiveLock);
07878 
07879     heap_freetuple(newtuple);
07880 }
07881 
07882 /*
07883  * Cleanup after we've finished all the ALTER TYPE operations for a
07884  * particular relation.  We have to drop and recreate all the indexes
07885  * and constraints that depend on the altered columns.
07886  */
07887 static void
07888 ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode)
07889 {
07890     ObjectAddress obj;
07891     ListCell   *def_item;
07892     ListCell   *oid_item;
07893 
07894     /*
07895      * Re-parse the index and constraint definitions, and attach them to the
07896      * appropriate work queue entries.  We do this before dropping because in
07897      * the case of a FOREIGN KEY constraint, we might not yet have exclusive
07898      * lock on the table the constraint is attached to, and we need to get
07899      * that before dropping.  It's safe because the parser won't actually look
07900      * at the catalogs to detect the existing entry.
07901      */
07902     forboth(oid_item, tab->changedConstraintOids,
07903             def_item, tab->changedConstraintDefs)
07904         ATPostAlterTypeParse(lfirst_oid(oid_item), (char *) lfirst(def_item),
07905                              wqueue, lockmode, tab->rewrite);
07906     forboth(oid_item, tab->changedIndexOids,
07907             def_item, tab->changedIndexDefs)
07908         ATPostAlterTypeParse(lfirst_oid(oid_item), (char *) lfirst(def_item),
07909                              wqueue, lockmode, tab->rewrite);
07910 
07911     /*
07912      * Now we can drop the existing constraints and indexes --- constraints
07913      * first, since some of them might depend on the indexes.  In fact, we
07914      * have to delete FOREIGN KEY constraints before UNIQUE constraints, but
07915      * we already ordered the constraint list to ensure that would happen. It
07916      * should be okay to use DROP_RESTRICT here, since nothing else should be
07917      * depending on these objects.
07918      */
07919     foreach(oid_item, tab->changedConstraintOids)
07920     {
07921         obj.classId = ConstraintRelationId;
07922         obj.objectId = lfirst_oid(oid_item);
07923         obj.objectSubId = 0;
07924         performDeletion(&obj, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
07925     }
07926 
07927     foreach(oid_item, tab->changedIndexOids)
07928     {
07929         obj.classId = RelationRelationId;
07930         obj.objectId = lfirst_oid(oid_item);
07931         obj.objectSubId = 0;
07932         performDeletion(&obj, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
07933     }
07934 
07935     /*
07936      * The objects will get recreated during subsequent passes over the work
07937      * queue.
07938      */
07939 }
07940 
07941 static void
07942 ATPostAlterTypeParse(Oid oldId, char *cmd,
07943                      List **wqueue, LOCKMODE lockmode, bool rewrite)
07944 {
07945     List       *raw_parsetree_list;
07946     List       *querytree_list;
07947     ListCell   *list_item;
07948 
07949     /*
07950      * We expect that we will get only ALTER TABLE and CREATE INDEX
07951      * statements. Hence, there is no need to pass them through
07952      * parse_analyze() or the rewriter, but instead we need to pass them
07953      * through parse_utilcmd.c to make them ready for execution.
07954      */
07955     raw_parsetree_list = raw_parser(cmd);
07956     querytree_list = NIL;
07957     foreach(list_item, raw_parsetree_list)
07958     {
07959         Node       *stmt = (Node *) lfirst(list_item);
07960 
07961         if (IsA(stmt, IndexStmt))
07962             querytree_list = lappend(querytree_list,
07963                                      transformIndexStmt((IndexStmt *) stmt,
07964                                                         cmd));
07965         else if (IsA(stmt, AlterTableStmt))
07966             querytree_list = list_concat(querytree_list,
07967                              transformAlterTableStmt((AlterTableStmt *) stmt,
07968                                                      cmd));
07969         else
07970             querytree_list = lappend(querytree_list, stmt);
07971     }
07972 
07973     /*
07974      * Attach each generated command to the proper place in the work queue.
07975      * Note this could result in creation of entirely new work-queue entries.
07976      *
07977      * Also note that we have to tweak the command subtypes, because it turns
07978      * out that re-creation of indexes and constraints has to act a bit
07979      * differently from initial creation.
07980      */
07981     foreach(list_item, querytree_list)
07982     {
07983         Node       *stm = (Node *) lfirst(list_item);
07984         Relation    rel;
07985         AlteredTableInfo *tab;
07986 
07987         switch (nodeTag(stm))
07988         {
07989             case T_IndexStmt:
07990                 {
07991                     IndexStmt  *stmt = (IndexStmt *) stm;
07992                     AlterTableCmd *newcmd;
07993 
07994                     if (!rewrite)
07995                         TryReuseIndex(oldId, stmt);
07996 
07997                     rel = relation_openrv(stmt->relation, lockmode);
07998                     tab = ATGetQueueEntry(wqueue, rel);
07999                     newcmd = makeNode(AlterTableCmd);
08000                     newcmd->subtype = AT_ReAddIndex;
08001                     newcmd->def = (Node *) stmt;
08002                     tab->subcmds[AT_PASS_OLD_INDEX] =
08003                         lappend(tab->subcmds[AT_PASS_OLD_INDEX], newcmd);
08004                     relation_close(rel, NoLock);
08005                     break;
08006                 }
08007             case T_AlterTableStmt:
08008                 {
08009                     AlterTableStmt *stmt = (AlterTableStmt *) stm;
08010                     ListCell   *lcmd;
08011 
08012                     rel = relation_openrv(stmt->relation, lockmode);
08013                     tab = ATGetQueueEntry(wqueue, rel);
08014                     foreach(lcmd, stmt->cmds)
08015                     {
08016                         AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
08017                         Constraint *con;
08018 
08019                         switch (cmd->subtype)
08020                         {
08021                             case AT_AddIndex:
08022                                 Assert(IsA(cmd->def, IndexStmt));
08023                                 if (!rewrite)
08024                                     TryReuseIndex(get_constraint_index(oldId),
08025                                                   (IndexStmt *) cmd->def);
08026                                 cmd->subtype = AT_ReAddIndex;
08027                                 tab->subcmds[AT_PASS_OLD_INDEX] =
08028                                     lappend(tab->subcmds[AT_PASS_OLD_INDEX], cmd);
08029                                 break;
08030                             case AT_AddConstraint:
08031                                 Assert(IsA(cmd->def, Constraint));
08032                                 con = (Constraint *) cmd->def;
08033                                 /* rewriting neither side of a FK */
08034                                 if (con->contype == CONSTR_FOREIGN &&
08035                                     !rewrite && !tab->rewrite)
08036                                     TryReuseForeignKey(oldId, con);
08037                                 cmd->subtype = AT_ReAddConstraint;
08038                                 tab->subcmds[AT_PASS_OLD_CONSTR] =
08039                                     lappend(tab->subcmds[AT_PASS_OLD_CONSTR], cmd);
08040                                 break;
08041                             default:
08042                                 elog(ERROR, "unexpected statement type: %d",
08043                                      (int) cmd->subtype);
08044                         }
08045                     }
08046                     relation_close(rel, NoLock);
08047                     break;
08048                 }
08049             default:
08050                 elog(ERROR, "unexpected statement type: %d",
08051                      (int) nodeTag(stm));
08052         }
08053     }
08054 }
08055 
08056 /*
08057  * Subroutine for ATPostAlterTypeParse().  Calls out to CheckIndexCompatible()
08058  * for the real analysis, then mutates the IndexStmt based on that verdict.
08059  */
08060 static void
08061 TryReuseIndex(Oid oldId, IndexStmt *stmt)
08062 {
08063     if (CheckIndexCompatible(oldId,
08064                              stmt->relation,
08065                              stmt->accessMethod,
08066                              stmt->indexParams,
08067                              stmt->excludeOpNames))
08068     {
08069         Relation    irel = index_open(oldId, NoLock);
08070 
08071         stmt->oldNode = irel->rd_node.relNode;
08072         index_close(irel, NoLock);
08073     }
08074 }
08075 
08076 /*
08077  * Subroutine for ATPostAlterTypeParse().
08078  *
08079  * Stash the old P-F equality operator into the Constraint node, for possible
08080  * use by ATAddForeignKeyConstraint() in determining whether revalidation of
08081  * this constraint can be skipped.
08082  */
08083 static void
08084 TryReuseForeignKey(Oid oldId, Constraint *con)
08085 {
08086     HeapTuple   tup;
08087     Datum       adatum;
08088     bool        isNull;
08089     ArrayType  *arr;
08090     Oid        *rawarr;
08091     int         numkeys;
08092     int         i;
08093 
08094     Assert(con->contype == CONSTR_FOREIGN);
08095     Assert(con->old_conpfeqop == NIL);  /* already prepared this node */
08096 
08097     tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(oldId));
08098     if (!HeapTupleIsValid(tup)) /* should not happen */
08099         elog(ERROR, "cache lookup failed for constraint %u", oldId);
08100 
08101     adatum = SysCacheGetAttr(CONSTROID, tup,
08102                              Anum_pg_constraint_conpfeqop, &isNull);
08103     if (isNull)
08104         elog(ERROR, "null conpfeqop for constraint %u", oldId);
08105     arr = DatumGetArrayTypeP(adatum);   /* ensure not toasted */
08106     numkeys = ARR_DIMS(arr)[0];
08107     /* test follows the one in ri_FetchConstraintInfo() */
08108     if (ARR_NDIM(arr) != 1 ||
08109         ARR_HASNULL(arr) ||
08110         ARR_ELEMTYPE(arr) != OIDOID)
08111         elog(ERROR, "conpfeqop is not a 1-D Oid array");
08112     rawarr = (Oid *) ARR_DATA_PTR(arr);
08113 
08114     /* stash a List of the operator Oids in our Constraint node */
08115     for (i = 0; i < numkeys; i++)
08116         con->old_conpfeqop = lcons_oid(rawarr[i], con->old_conpfeqop);
08117 
08118     ReleaseSysCache(tup);
08119 }
08120 
08121 /*
08122  * ALTER TABLE OWNER
08123  *
08124  * recursing is true if we are recursing from a table to its indexes,
08125  * sequences, or toast table.  We don't allow the ownership of those things to
08126  * be changed separately from the parent table.  Also, we can skip permission
08127  * checks (this is necessary not just an optimization, else we'd fail to
08128  * handle toast tables properly).
08129  *
08130  * recursing is also true if ALTER TYPE OWNER is calling us to fix up a
08131  * free-standing composite type.
08132  */
08133 void
08134 ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lockmode)
08135 {
08136     Relation    target_rel;
08137     Relation    class_rel;
08138     HeapTuple   tuple;
08139     Form_pg_class tuple_class;
08140 
08141     /*
08142      * Get exclusive lock till end of transaction on the target table. Use
08143      * relation_open so that we can work on indexes and sequences.
08144      */
08145     target_rel = relation_open(relationOid, lockmode);
08146 
08147     /* Get its pg_class tuple, too */
08148     class_rel = heap_open(RelationRelationId, RowExclusiveLock);
08149 
08150     tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relationOid));
08151     if (!HeapTupleIsValid(tuple))
08152         elog(ERROR, "cache lookup failed for relation %u", relationOid);
08153     tuple_class = (Form_pg_class) GETSTRUCT(tuple);
08154 
08155     /* Can we change the ownership of this tuple? */
08156     switch (tuple_class->relkind)
08157     {
08158         case RELKIND_RELATION:
08159         case RELKIND_VIEW:
08160         case RELKIND_MATVIEW:
08161         case RELKIND_FOREIGN_TABLE:
08162             /* ok to change owner */
08163             break;
08164         case RELKIND_INDEX:
08165             if (!recursing)
08166             {
08167                 /*
08168                  * Because ALTER INDEX OWNER used to be allowed, and in fact
08169                  * is generated by old versions of pg_dump, we give a warning
08170                  * and do nothing rather than erroring out.  Also, to avoid
08171                  * unnecessary chatter while restoring those old dumps, say
08172                  * nothing at all if the command would be a no-op anyway.
08173                  */
08174                 if (tuple_class->relowner != newOwnerId)
08175                     ereport(WARNING,
08176                             (errcode(ERRCODE_WRONG_OBJECT_TYPE),
08177                              errmsg("cannot change owner of index \"%s\"",
08178                                     NameStr(tuple_class->relname)),
08179                              errhint("Change the ownership of the index's table, instead.")));
08180                 /* quick hack to exit via the no-op path */
08181                 newOwnerId = tuple_class->relowner;
08182             }
08183             break;
08184         case RELKIND_SEQUENCE:
08185             if (!recursing &&
08186                 tuple_class->relowner != newOwnerId)
08187             {
08188                 /* if it's an owned sequence, disallow changing it by itself */
08189                 Oid         tableId;
08190                 int32       colId;
08191 
08192                 if (sequenceIsOwned(relationOid, &tableId, &colId))
08193                     ereport(ERROR,
08194                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
08195                              errmsg("cannot change owner of sequence \"%s\"",
08196                                     NameStr(tuple_class->relname)),
08197                       errdetail("Sequence \"%s\" is linked to table \"%s\".",
08198                                 NameStr(tuple_class->relname),
08199                                 get_rel_name(tableId))));
08200             }
08201             break;
08202         case RELKIND_COMPOSITE_TYPE:
08203             if (recursing)
08204                 break;
08205             ereport(ERROR,
08206                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
08207                      errmsg("\"%s\" is a composite type",
08208                             NameStr(tuple_class->relname)),
08209                      errhint("Use ALTER TYPE instead.")));
08210             break;
08211         case RELKIND_TOASTVALUE:
08212             if (recursing)
08213                 break;
08214             /* FALL THRU */
08215         default:
08216             ereport(ERROR,
08217                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
08218             errmsg("\"%s\" is not a table, view, sequence, or foreign table",
08219                    NameStr(tuple_class->relname))));
08220     }
08221 
08222     /*
08223      * If the new owner is the same as the existing owner, consider the
08224      * command to have succeeded.  This is for dump restoration purposes.
08225      */
08226     if (tuple_class->relowner != newOwnerId)
08227     {
08228         Datum       repl_val[Natts_pg_class];
08229         bool        repl_null[Natts_pg_class];
08230         bool        repl_repl[Natts_pg_class];
08231         Acl        *newAcl;
08232         Datum       aclDatum;
08233         bool        isNull;
08234         HeapTuple   newtuple;
08235 
08236         /* skip permission checks when recursing to index or toast table */
08237         if (!recursing)
08238         {
08239             /* Superusers can always do it */
08240             if (!superuser())
08241             {
08242                 Oid         namespaceOid = tuple_class->relnamespace;
08243                 AclResult   aclresult;
08244 
08245                 /* Otherwise, must be owner of the existing object */
08246                 if (!pg_class_ownercheck(relationOid, GetUserId()))
08247                     aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
08248                                    RelationGetRelationName(target_rel));
08249 
08250                 /* Must be able to become new owner */
08251                 check_is_member_of_role(GetUserId(), newOwnerId);
08252 
08253                 /* New owner must have CREATE privilege on namespace */
08254                 aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
08255                                                   ACL_CREATE);
08256                 if (aclresult != ACLCHECK_OK)
08257                     aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
08258                                    get_namespace_name(namespaceOid));
08259             }
08260         }
08261 
08262         memset(repl_null, false, sizeof(repl_null));
08263         memset(repl_repl, false, sizeof(repl_repl));
08264 
08265         repl_repl[Anum_pg_class_relowner - 1] = true;
08266         repl_val[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(newOwnerId);
08267 
08268         /*
08269          * Determine the modified ACL for the new owner.  This is only
08270          * necessary when the ACL is non-null.
08271          */
08272         aclDatum = SysCacheGetAttr(RELOID, tuple,
08273                                    Anum_pg_class_relacl,
08274                                    &isNull);
08275         if (!isNull)
08276         {
08277             newAcl = aclnewowner(DatumGetAclP(aclDatum),
08278                                  tuple_class->relowner, newOwnerId);
08279             repl_repl[Anum_pg_class_relacl - 1] = true;
08280             repl_val[Anum_pg_class_relacl - 1] = PointerGetDatum(newAcl);
08281         }
08282 
08283         newtuple = heap_modify_tuple(tuple, RelationGetDescr(class_rel), repl_val, repl_null, repl_repl);
08284 
08285         simple_heap_update(class_rel, &newtuple->t_self, newtuple);
08286         CatalogUpdateIndexes(class_rel, newtuple);
08287 
08288         heap_freetuple(newtuple);
08289 
08290         /*
08291          * We must similarly update any per-column ACLs to reflect the new
08292          * owner; for neatness reasons that's split out as a subroutine.
08293          */
08294         change_owner_fix_column_acls(relationOid,
08295                                      tuple_class->relowner,
08296                                      newOwnerId);
08297 
08298         /*
08299          * Update owner dependency reference, if any.  A composite type has
08300          * none, because it's tracked for the pg_type entry instead of here;
08301          * indexes and TOAST tables don't have their own entries either.
08302          */
08303         if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE &&
08304             tuple_class->relkind != RELKIND_INDEX &&
08305             tuple_class->relkind != RELKIND_TOASTVALUE)
08306             changeDependencyOnOwner(RelationRelationId, relationOid,
08307                                     newOwnerId);
08308 
08309         /*
08310          * Also change the ownership of the table's row type, if it has one
08311          */
08312         if (tuple_class->relkind != RELKIND_INDEX)
08313             AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId,
08314                              tuple_class->relkind == RELKIND_COMPOSITE_TYPE);
08315 
08316         /*
08317          * If we are operating on a table or materialized view, also change
08318          * the ownership of any indexes and sequences that belong to the
08319          * relation, as well as its toast table (if it has one).
08320          */
08321         if (tuple_class->relkind == RELKIND_RELATION ||
08322             tuple_class->relkind == RELKIND_MATVIEW ||
08323             tuple_class->relkind == RELKIND_TOASTVALUE)
08324         {
08325             List       *index_oid_list;
08326             ListCell   *i;
08327 
08328             /* Find all the indexes belonging to this relation */
08329             index_oid_list = RelationGetIndexList(target_rel);
08330 
08331             /* For each index, recursively change its ownership */
08332             foreach(i, index_oid_list)
08333                 ATExecChangeOwner(lfirst_oid(i), newOwnerId, true, lockmode);
08334 
08335             list_free(index_oid_list);
08336         }
08337 
08338         if (tuple_class->relkind == RELKIND_RELATION ||
08339             tuple_class->relkind == RELKIND_MATVIEW)
08340         {
08341             /* If it has a toast table, recurse to change its ownership */
08342             if (tuple_class->reltoastrelid != InvalidOid)
08343                 ATExecChangeOwner(tuple_class->reltoastrelid, newOwnerId,
08344                                   true, lockmode);
08345 
08346             /* If it has dependent sequences, recurse to change them too */
08347             change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
08348         }
08349     }
08350 
08351     InvokeObjectPostAlterHook(RelationRelationId, relationOid, 0);
08352 
08353     ReleaseSysCache(tuple);
08354     heap_close(class_rel, RowExclusiveLock);
08355     relation_close(target_rel, NoLock);
08356 }
08357 
08358 /*
08359  * change_owner_fix_column_acls
08360  *
08361  * Helper function for ATExecChangeOwner.  Scan the columns of the table
08362  * and fix any non-null column ACLs to reflect the new owner.
08363  */
08364 static void
08365 change_owner_fix_column_acls(Oid relationOid, Oid oldOwnerId, Oid newOwnerId)
08366 {
08367     Relation    attRelation;
08368     SysScanDesc scan;
08369     ScanKeyData key[1];
08370     HeapTuple   attributeTuple;
08371 
08372     attRelation = heap_open(AttributeRelationId, RowExclusiveLock);
08373     ScanKeyInit(&key[0],
08374                 Anum_pg_attribute_attrelid,
08375                 BTEqualStrategyNumber, F_OIDEQ,
08376                 ObjectIdGetDatum(relationOid));
08377     scan = systable_beginscan(attRelation, AttributeRelidNumIndexId,
08378                               true, SnapshotNow, 1, key);
08379     while (HeapTupleIsValid(attributeTuple = systable_getnext(scan)))
08380     {
08381         Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple);
08382         Datum       repl_val[Natts_pg_attribute];
08383         bool        repl_null[Natts_pg_attribute];
08384         bool        repl_repl[Natts_pg_attribute];
08385         Acl        *newAcl;
08386         Datum       aclDatum;
08387         bool        isNull;
08388         HeapTuple   newtuple;
08389 
08390         /* Ignore dropped columns */
08391         if (att->attisdropped)
08392             continue;
08393 
08394         aclDatum = heap_getattr(attributeTuple,
08395                                 Anum_pg_attribute_attacl,
08396                                 RelationGetDescr(attRelation),
08397                                 &isNull);
08398         /* Null ACLs do not require changes */
08399         if (isNull)
08400             continue;
08401 
08402         memset(repl_null, false, sizeof(repl_null));
08403         memset(repl_repl, false, sizeof(repl_repl));
08404 
08405         newAcl = aclnewowner(DatumGetAclP(aclDatum),
08406                              oldOwnerId, newOwnerId);
08407         repl_repl[Anum_pg_attribute_attacl - 1] = true;
08408         repl_val[Anum_pg_attribute_attacl - 1] = PointerGetDatum(newAcl);
08409 
08410         newtuple = heap_modify_tuple(attributeTuple,
08411                                      RelationGetDescr(attRelation),
08412                                      repl_val, repl_null, repl_repl);
08413 
08414         simple_heap_update(attRelation, &newtuple->t_self, newtuple);
08415         CatalogUpdateIndexes(attRelation, newtuple);
08416 
08417         heap_freetuple(newtuple);
08418     }
08419     systable_endscan(scan);
08420     heap_close(attRelation, RowExclusiveLock);
08421 }
08422 
08423 /*
08424  * change_owner_recurse_to_sequences
08425  *
08426  * Helper function for ATExecChangeOwner.  Examines pg_depend searching
08427  * for sequences that are dependent on serial columns, and changes their
08428  * ownership.
08429  */
08430 static void
08431 change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId, LOCKMODE lockmode)
08432 {
08433     Relation    depRel;
08434     SysScanDesc scan;
08435     ScanKeyData key[2];
08436     HeapTuple   tup;
08437 
08438     /*
08439      * SERIAL sequences are those having an auto dependency on one of the
08440      * table's columns (we don't care *which* column, exactly).
08441      */
08442     depRel = heap_open(DependRelationId, AccessShareLock);
08443 
08444     ScanKeyInit(&key[0],
08445                 Anum_pg_depend_refclassid,
08446                 BTEqualStrategyNumber, F_OIDEQ,
08447                 ObjectIdGetDatum(RelationRelationId));
08448     ScanKeyInit(&key[1],
08449                 Anum_pg_depend_refobjid,
08450                 BTEqualStrategyNumber, F_OIDEQ,
08451                 ObjectIdGetDatum(relationOid));
08452     /* we leave refobjsubid unspecified */
08453 
08454     scan = systable_beginscan(depRel, DependReferenceIndexId, true,
08455                               SnapshotNow, 2, key);
08456 
08457     while (HeapTupleIsValid(tup = systable_getnext(scan)))
08458     {
08459         Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
08460         Relation    seqRel;
08461 
08462         /* skip dependencies other than auto dependencies on columns */
08463         if (depForm->refobjsubid == 0 ||
08464             depForm->classid != RelationRelationId ||
08465             depForm->objsubid != 0 ||
08466             depForm->deptype != DEPENDENCY_AUTO)
08467             continue;
08468 
08469         /* Use relation_open just in case it's an index */
08470         seqRel = relation_open(depForm->objid, lockmode);
08471 
08472         /* skip non-sequence relations */
08473         if (RelationGetForm(seqRel)->relkind != RELKIND_SEQUENCE)
08474         {
08475             /* No need to keep the lock */
08476             relation_close(seqRel, lockmode);
08477             continue;
08478         }
08479 
08480         /* We don't need to close the sequence while we alter it. */
08481         ATExecChangeOwner(depForm->objid, newOwnerId, true, lockmode);
08482 
08483         /* Now we can close it.  Keep the lock till end of transaction. */
08484         relation_close(seqRel, NoLock);
08485     }
08486 
08487     systable_endscan(scan);
08488 
08489     relation_close(depRel, AccessShareLock);
08490 }
08491 
08492 /*
08493  * ALTER TABLE CLUSTER ON
08494  *
08495  * The only thing we have to do is to change the indisclustered bits.
08496  */
08497 static void
08498 ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode)
08499 {
08500     Oid         indexOid;
08501 
08502     indexOid = get_relname_relid(indexName, rel->rd_rel->relnamespace);
08503 
08504     if (!OidIsValid(indexOid))
08505         ereport(ERROR,
08506                 (errcode(ERRCODE_UNDEFINED_OBJECT),
08507                  errmsg("index \"%s\" for table \"%s\" does not exist",
08508                         indexName, RelationGetRelationName(rel))));
08509 
08510     /* Check index is valid to cluster on */
08511     check_index_is_clusterable(rel, indexOid, false, lockmode);
08512 
08513     /* And do the work */
08514     mark_index_clustered(rel, indexOid, false);
08515 }
08516 
08517 /*
08518  * ALTER TABLE SET WITHOUT CLUSTER
08519  *
08520  * We have to find any indexes on the table that have indisclustered bit
08521  * set and turn it off.
08522  */
08523 static void
08524 ATExecDropCluster(Relation rel, LOCKMODE lockmode)
08525 {
08526     mark_index_clustered(rel, InvalidOid, false);
08527 }
08528 
08529 /*
08530  * ALTER TABLE SET TABLESPACE
08531  */
08532 static void
08533 ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename, LOCKMODE lockmode)
08534 {
08535     Oid         tablespaceId;
08536     AclResult   aclresult;
08537 
08538     /* Check that the tablespace exists */
08539     tablespaceId = get_tablespace_oid(tablespacename, false);
08540 
08541     /* Check its permissions */
08542     aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(), ACL_CREATE);
08543     if (aclresult != ACLCHECK_OK)
08544         aclcheck_error(aclresult, ACL_KIND_TABLESPACE, tablespacename);
08545 
08546     /* Save info for Phase 3 to do the real work */
08547     if (OidIsValid(tab->newTableSpace))
08548         ereport(ERROR,
08549                 (errcode(ERRCODE_SYNTAX_ERROR),
08550                  errmsg("cannot have multiple SET TABLESPACE subcommands")));
08551     tab->newTableSpace = tablespaceId;
08552 }
08553 
08554 /*
08555  * Set, reset, or replace reloptions.
08556  */
08557 static void
08558 ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
08559                     LOCKMODE lockmode)
08560 {
08561     Oid         relid;
08562     Relation    pgclass;
08563     HeapTuple   tuple;
08564     HeapTuple   newtuple;
08565     Datum       datum;
08566     bool        isnull;
08567     Datum       newOptions;
08568     Datum       repl_val[Natts_pg_class];
08569     bool        repl_null[Natts_pg_class];
08570     bool        repl_repl[Natts_pg_class];
08571     static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
08572 
08573     if (defList == NIL && operation != AT_ReplaceRelOptions)
08574         return;                 /* nothing to do */
08575 
08576     pgclass = heap_open(RelationRelationId, RowExclusiveLock);
08577 
08578     /* Fetch heap tuple */
08579     relid = RelationGetRelid(rel);
08580     tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
08581     if (!HeapTupleIsValid(tuple))
08582         elog(ERROR, "cache lookup failed for relation %u", relid);
08583 
08584     if (operation == AT_ReplaceRelOptions)
08585     {
08586         /*
08587          * If we're supposed to replace the reloptions list, we just pretend
08588          * there were none before.
08589          */
08590         datum = (Datum) 0;
08591         isnull = true;
08592     }
08593     else
08594     {
08595         /* Get the old reloptions */
08596         datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
08597                                 &isnull);
08598     }
08599 
08600     /* Generate new proposed reloptions (text array) */
08601     newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
08602                                      defList, NULL, validnsps, false,
08603                                      operation == AT_ResetRelOptions);
08604 
08605     /* Validate */
08606     switch (rel->rd_rel->relkind)
08607     {
08608         case RELKIND_RELATION:
08609         case RELKIND_TOASTVALUE:
08610         case RELKIND_VIEW:
08611         case RELKIND_MATVIEW:
08612             (void) heap_reloptions(rel->rd_rel->relkind, newOptions, true);
08613             break;
08614         case RELKIND_INDEX:
08615             (void) index_reloptions(rel->rd_am->amoptions, newOptions, true);
08616             break;
08617         default:
08618             ereport(ERROR,
08619                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
08620                      errmsg("\"%s\" is not a table, view, materialized view, index, or TOAST table",
08621                             RelationGetRelationName(rel))));
08622             break;
08623     }
08624 
08625     /*
08626      * All we need do here is update the pg_class row; the new options will be
08627      * propagated into relcaches during post-commit cache inval.
08628      */
08629     memset(repl_val, 0, sizeof(repl_val));
08630     memset(repl_null, false, sizeof(repl_null));
08631     memset(repl_repl, false, sizeof(repl_repl));
08632 
08633     if (newOptions != (Datum) 0)
08634         repl_val[Anum_pg_class_reloptions - 1] = newOptions;
08635     else
08636         repl_null[Anum_pg_class_reloptions - 1] = true;
08637 
08638     repl_repl[Anum_pg_class_reloptions - 1] = true;
08639 
08640     newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass),
08641                                  repl_val, repl_null, repl_repl);
08642 
08643     simple_heap_update(pgclass, &newtuple->t_self, newtuple);
08644 
08645     CatalogUpdateIndexes(pgclass, newtuple);
08646 
08647     InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
08648 
08649     heap_freetuple(newtuple);
08650 
08651     ReleaseSysCache(tuple);
08652 
08653     /* repeat the whole exercise for the toast table, if there's one */
08654     if (OidIsValid(rel->rd_rel->reltoastrelid))
08655     {
08656         Relation    toastrel;
08657         Oid         toastid = rel->rd_rel->reltoastrelid;
08658 
08659         toastrel = heap_open(toastid, lockmode);
08660 
08661         /* Fetch heap tuple */
08662         tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(toastid));
08663         if (!HeapTupleIsValid(tuple))
08664             elog(ERROR, "cache lookup failed for relation %u", toastid);
08665 
08666         if (operation == AT_ReplaceRelOptions)
08667         {
08668             /*
08669              * If we're supposed to replace the reloptions list, we just
08670              * pretend there were none before.
08671              */
08672             datum = (Datum) 0;
08673             isnull = true;
08674         }
08675         else
08676         {
08677             /* Get the old reloptions */
08678             datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
08679                                     &isnull);
08680         }
08681 
08682         newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
08683                                          defList, "toast", validnsps, false,
08684                                          operation == AT_ResetRelOptions);
08685 
08686         (void) heap_reloptions(RELKIND_TOASTVALUE, newOptions, true);
08687 
08688         memset(repl_val, 0, sizeof(repl_val));
08689         memset(repl_null, false, sizeof(repl_null));
08690         memset(repl_repl, false, sizeof(repl_repl));
08691 
08692         if (newOptions != (Datum) 0)
08693             repl_val[Anum_pg_class_reloptions - 1] = newOptions;
08694         else
08695             repl_null[Anum_pg_class_reloptions - 1] = true;
08696 
08697         repl_repl[Anum_pg_class_reloptions - 1] = true;
08698 
08699         newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass),
08700                                      repl_val, repl_null, repl_repl);
08701 
08702         simple_heap_update(pgclass, &newtuple->t_self, newtuple);
08703 
08704         CatalogUpdateIndexes(pgclass, newtuple);
08705 
08706         InvokeObjectPostAlterHookArg(RelationRelationId,
08707                                      RelationGetRelid(toastrel), 0,
08708                                      InvalidOid, true);
08709 
08710         heap_freetuple(newtuple);
08711 
08712         ReleaseSysCache(tuple);
08713 
08714         heap_close(toastrel, NoLock);
08715     }
08716 
08717     heap_close(pgclass, RowExclusiveLock);
08718 }
08719 
08720 /*
08721  * Execute ALTER TABLE SET TABLESPACE for cases where there is no tuple
08722  * rewriting to be done, so we just want to copy the data as fast as possible.
08723  */
08724 static void
08725 ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
08726 {
08727     Relation    rel;
08728     Oid         oldTableSpace;
08729     Oid         reltoastrelid;
08730     Oid         reltoastidxid;
08731     Oid         newrelfilenode;
08732     RelFileNode newrnode;
08733     SMgrRelation dstrel;
08734     Relation    pg_class;
08735     HeapTuple   tuple;
08736     Form_pg_class rd_rel;
08737     ForkNumber  forkNum;
08738 
08739     /*
08740      * Need lock here in case we are recursing to toast table or index
08741      */
08742     rel = relation_open(tableOid, lockmode);
08743 
08744     /*
08745      * No work if no change in tablespace.
08746      */
08747     oldTableSpace = rel->rd_rel->reltablespace;
08748     if (newTableSpace == oldTableSpace ||
08749         (newTableSpace == MyDatabaseTableSpace && oldTableSpace == 0))
08750     {
08751         InvokeObjectPostAlterHook(RelationRelationId,
08752                                   RelationGetRelid(rel), 0);
08753 
08754         relation_close(rel, NoLock);
08755         return;
08756     }
08757 
08758     /*
08759      * We cannot support moving mapped relations into different tablespaces.
08760      * (In particular this eliminates all shared catalogs.)
08761      */
08762     if (RelationIsMapped(rel))
08763         ereport(ERROR,
08764                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
08765                  errmsg("cannot move system relation \"%s\"",
08766                         RelationGetRelationName(rel))));
08767 
08768     /* Can't move a non-shared relation into pg_global */
08769     if (newTableSpace == GLOBALTABLESPACE_OID)
08770         ereport(ERROR,
08771                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
08772                  errmsg("only shared relations can be placed in pg_global tablespace")));
08773 
08774     /*
08775      * Don't allow moving temp tables of other backends ... their local buffer
08776      * manager is not going to cope.
08777      */
08778     if (RELATION_IS_OTHER_TEMP(rel))
08779         ereport(ERROR,
08780                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
08781                  errmsg("cannot move temporary tables of other sessions")));
08782 
08783     reltoastrelid = rel->rd_rel->reltoastrelid;
08784     reltoastidxid = rel->rd_rel->reltoastidxid;
08785 
08786     /* Get a modifiable copy of the relation's pg_class row */
08787     pg_class = heap_open(RelationRelationId, RowExclusiveLock);
08788 
08789     tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(tableOid));
08790     if (!HeapTupleIsValid(tuple))
08791         elog(ERROR, "cache lookup failed for relation %u", tableOid);
08792     rd_rel = (Form_pg_class) GETSTRUCT(tuple);
08793 
08794     /*
08795      * Since we copy the file directly without looking at the shared buffers,
08796      * we'd better first flush out any pages of the source relation that are
08797      * in shared buffers.  We assume no new changes will be made while we are
08798      * holding exclusive lock on the rel.
08799      */
08800     FlushRelationBuffers(rel);
08801 
08802     /*
08803      * Relfilenodes are not unique across tablespaces, so we need to allocate
08804      * a new one in the new tablespace.
08805      */
08806     newrelfilenode = GetNewRelFileNode(newTableSpace, NULL,
08807                                        rel->rd_rel->relpersistence);
08808 
08809     /* Open old and new relation */
08810     newrnode = rel->rd_node;
08811     newrnode.relNode = newrelfilenode;
08812     newrnode.spcNode = newTableSpace;
08813     dstrel = smgropen(newrnode, rel->rd_backend);
08814 
08815     RelationOpenSmgr(rel);
08816 
08817     /*
08818      * Create and copy all forks of the relation, and schedule unlinking of
08819      * old physical files.
08820      *
08821      * NOTE: any conflict in relfilenode value will be caught in
08822      * RelationCreateStorage().
08823      */
08824     RelationCreateStorage(newrnode, rel->rd_rel->relpersistence);
08825 
08826     /* copy main fork */
08827     copy_relation_data(rel->rd_smgr, dstrel, MAIN_FORKNUM,
08828                        rel->rd_rel->relpersistence);
08829 
08830     /* copy those extra forks that exist */
08831     for (forkNum = MAIN_FORKNUM + 1; forkNum <= MAX_FORKNUM; forkNum++)
08832     {
08833         if (smgrexists(rel->rd_smgr, forkNum))
08834         {
08835             smgrcreate(dstrel, forkNum, false);
08836             copy_relation_data(rel->rd_smgr, dstrel, forkNum,
08837                                rel->rd_rel->relpersistence);
08838         }
08839     }
08840 
08841     /* drop old relation, and close new one */
08842     RelationDropStorage(rel);
08843     smgrclose(dstrel);
08844 
08845     /* update the pg_class row */
08846     rd_rel->reltablespace = (newTableSpace == MyDatabaseTableSpace) ? InvalidOid : newTableSpace;
08847     rd_rel->relfilenode = newrelfilenode;
08848     simple_heap_update(pg_class, &tuple->t_self, tuple);
08849     CatalogUpdateIndexes(pg_class, tuple);
08850 
08851     InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
08852 
08853     heap_freetuple(tuple);
08854 
08855     heap_close(pg_class, RowExclusiveLock);
08856 
08857     relation_close(rel, NoLock);
08858 
08859     /* Make sure the reltablespace change is visible */
08860     CommandCounterIncrement();
08861 
08862     /* Move associated toast relation and/or index, too */
08863     if (OidIsValid(reltoastrelid))
08864         ATExecSetTableSpace(reltoastrelid, newTableSpace, lockmode);
08865     if (OidIsValid(reltoastidxid))
08866         ATExecSetTableSpace(reltoastidxid, newTableSpace, lockmode);
08867 }
08868 
08869 /*
08870  * Copy data, block by block
08871  */
08872 static void
08873 copy_relation_data(SMgrRelation src, SMgrRelation dst,
08874                    ForkNumber forkNum, char relpersistence)
08875 {
08876     char       *buf;
08877     Page        page;
08878     bool        use_wal;
08879     BlockNumber nblocks;
08880     BlockNumber blkno;
08881 
08882     /*
08883      * palloc the buffer so that it's MAXALIGN'd.  If it were just a local
08884      * char[] array, the compiler might align it on any byte boundary, which
08885      * can seriously hurt transfer speed to and from the kernel; not to
08886      * mention possibly making log_newpage's accesses to the page header fail.
08887      */
08888     buf = (char *) palloc(BLCKSZ);
08889     page = (Page) buf;
08890 
08891     /*
08892      * We need to log the copied data in WAL iff WAL archiving/streaming is
08893      * enabled AND it's a permanent relation.
08894      */
08895     use_wal = XLogIsNeeded() && relpersistence == RELPERSISTENCE_PERMANENT;
08896 
08897     nblocks = smgrnblocks(src, forkNum);
08898 
08899     for (blkno = 0; blkno < nblocks; blkno++)
08900     {
08901         /* If we got a cancel signal during the copy of the data, quit */
08902         CHECK_FOR_INTERRUPTS();
08903 
08904         smgrread(src, forkNum, blkno, buf);
08905 
08906         if (!PageIsVerified(page, blkno))
08907             ereport(ERROR,
08908                     (errcode(ERRCODE_DATA_CORRUPTED),
08909                      errmsg("invalid page in block %u of relation %s",
08910                             blkno,
08911                             relpathbackend(src->smgr_rnode.node,
08912                                            src->smgr_rnode.backend,
08913                                            forkNum))));
08914 
08915         /* XLOG stuff */
08916         if (use_wal)
08917             log_newpage(&dst->smgr_rnode.node, forkNum, blkno, page);
08918 
08919         PageSetChecksumInplace(page, blkno);
08920 
08921         /*
08922          * Now write the page.  We say isTemp = true even if it's not a temp
08923          * rel, because there's no need for smgr to schedule an fsync for this
08924          * write; we'll do it ourselves below.
08925          */
08926         smgrextend(dst, forkNum, blkno, buf, true);
08927     }
08928 
08929     pfree(buf);
08930 
08931     /*
08932      * If the rel is WAL-logged, must fsync before commit.  We use heap_sync
08933      * to ensure that the toast table gets fsync'd too.  (For a temp or
08934      * unlogged rel we don't care since the data will be gone after a crash
08935      * anyway.)
08936      *
08937      * It's obvious that we must do this when not WAL-logging the copy. It's
08938      * less obvious that we have to do it even if we did WAL-log the copied
08939      * pages. The reason is that since we're copying outside shared buffers, a
08940      * CHECKPOINT occurring during the copy has no way to flush the previously
08941      * written data to disk (indeed it won't know the new rel even exists).  A
08942      * crash later on would replay WAL from the checkpoint, therefore it
08943      * wouldn't replay our earlier WAL entries. If we do not fsync those pages
08944      * here, they might still not be on disk when the crash occurs.
08945      */
08946     if (relpersistence == RELPERSISTENCE_PERMANENT)
08947         smgrimmedsync(dst, forkNum);
08948 }
08949 
08950 /*
08951  * ALTER TABLE ENABLE/DISABLE TRIGGER
08952  *
08953  * We just pass this off to trigger.c.
08954  */
08955 static void
08956 ATExecEnableDisableTrigger(Relation rel, char *trigname,
08957                         char fires_when, bool skip_system, LOCKMODE lockmode)
08958 {
08959     EnableDisableTrigger(rel, trigname, fires_when, skip_system);
08960 }
08961 
08962 /*
08963  * ALTER TABLE ENABLE/DISABLE RULE
08964  *
08965  * We just pass this off to rewriteDefine.c.
08966  */
08967 static void
08968 ATExecEnableDisableRule(Relation rel, char *trigname,
08969                         char fires_when, LOCKMODE lockmode)
08970 {
08971     EnableDisableRule(rel, trigname, fires_when);
08972 }
08973 
08974 /*
08975  * ALTER TABLE INHERIT
08976  *
08977  * Add a parent to the child's parents. This verifies that all the columns and
08978  * check constraints of the parent appear in the child and that they have the
08979  * same data types and expressions.
08980  */
08981 static void
08982 ATPrepAddInherit(Relation child_rel)
08983 {
08984     if (child_rel->rd_rel->reloftype)
08985         ereport(ERROR,
08986                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
08987                  errmsg("cannot change inheritance of typed table")));
08988 }
08989 
08990 static void
08991 ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
08992 {
08993     Relation    parent_rel,
08994                 catalogRelation;
08995     SysScanDesc scan;
08996     ScanKeyData key;
08997     HeapTuple   inheritsTuple;
08998     int32       inhseqno;
08999     List       *children;
09000 
09001     /*
09002      * A self-exclusive lock is needed here.  See the similar case in
09003      * MergeAttributes() for a full explanation.
09004      */
09005     parent_rel = heap_openrv(parent, ShareUpdateExclusiveLock);
09006 
09007     /*
09008      * Must be owner of both parent and child -- child was checked by
09009      * ATSimplePermissions call in ATPrepCmd
09010      */
09011     ATSimplePermissions(parent_rel, ATT_TABLE);
09012 
09013     /* Permanent rels cannot inherit from temporary ones */
09014     if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
09015         child_rel->rd_rel->relpersistence != RELPERSISTENCE_TEMP)
09016         ereport(ERROR,
09017                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
09018                  errmsg("cannot inherit from temporary relation \"%s\"",
09019                         RelationGetRelationName(parent_rel))));
09020 
09021     /* If parent rel is temp, it must belong to this session */
09022     if (parent_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
09023         !parent_rel->rd_islocaltemp)
09024         ereport(ERROR,
09025                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
09026                  errmsg("cannot inherit from temporary relation of another session")));
09027 
09028     /* Ditto for the child */
09029     if (child_rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP &&
09030         !child_rel->rd_islocaltemp)
09031         ereport(ERROR,
09032                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
09033                  errmsg("cannot inherit to temporary relation of another session")));
09034 
09035     /*
09036      * Check for duplicates in the list of parents, and determine the highest
09037      * inhseqno already present; we'll use the next one for the new parent.
09038      * (Note: get RowExclusiveLock because we will write pg_inherits below.)
09039      *
09040      * Note: we do not reject the case where the child already inherits from
09041      * the parent indirectly; CREATE TABLE doesn't reject comparable cases.
09042      */
09043     catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
09044     ScanKeyInit(&key,
09045                 Anum_pg_inherits_inhrelid,
09046                 BTEqualStrategyNumber, F_OIDEQ,
09047                 ObjectIdGetDatum(RelationGetRelid(child_rel)));
09048     scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
09049                               true, SnapshotNow, 1, &key);
09050 
09051     /* inhseqno sequences start at 1 */
09052     inhseqno = 0;
09053     while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
09054     {
09055         Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inheritsTuple);
09056 
09057         if (inh->inhparent == RelationGetRelid(parent_rel))
09058             ereport(ERROR,
09059                     (errcode(ERRCODE_DUPLICATE_TABLE),
09060              errmsg("relation \"%s\" would be inherited from more than once",
09061                     RelationGetRelationName(parent_rel))));
09062         if (inh->inhseqno > inhseqno)
09063             inhseqno = inh->inhseqno;
09064     }
09065     systable_endscan(scan);
09066 
09067     /*
09068      * Prevent circularity by seeing if proposed parent inherits from child.
09069      * (In particular, this disallows making a rel inherit from itself.)
09070      *
09071      * This is not completely bulletproof because of race conditions: in
09072      * multi-level inheritance trees, someone else could concurrently be
09073      * making another inheritance link that closes the loop but does not join
09074      * either of the rels we have locked.  Preventing that seems to require
09075      * exclusive locks on the entire inheritance tree, which is a cure worse
09076      * than the disease.  find_all_inheritors() will cope with circularity
09077      * anyway, so don't sweat it too much.
09078      *
09079      * We use weakest lock we can on child's children, namely AccessShareLock.
09080      */
09081     children = find_all_inheritors(RelationGetRelid(child_rel),
09082                                    AccessShareLock, NULL);
09083 
09084     if (list_member_oid(children, RelationGetRelid(parent_rel)))
09085         ereport(ERROR,
09086                 (errcode(ERRCODE_DUPLICATE_TABLE),
09087                  errmsg("circular inheritance not allowed"),
09088                  errdetail("\"%s\" is already a child of \"%s\".",
09089                            parent->relname,
09090                            RelationGetRelationName(child_rel))));
09091 
09092     /* If parent has OIDs then child must have OIDs */
09093     if (parent_rel->rd_rel->relhasoids && !child_rel->rd_rel->relhasoids)
09094         ereport(ERROR,
09095                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
09096                  errmsg("table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs",
09097                         RelationGetRelationName(child_rel),
09098                         RelationGetRelationName(parent_rel))));
09099 
09100     /* Match up the columns and bump attinhcount as needed */
09101     MergeAttributesIntoExisting(child_rel, parent_rel);
09102 
09103     /* Match up the constraints and bump coninhcount as needed */
09104     MergeConstraintsIntoExisting(child_rel, parent_rel);
09105 
09106     /*
09107      * OK, it looks valid.  Make the catalog entries that show inheritance.
09108      */
09109     StoreCatalogInheritance1(RelationGetRelid(child_rel),
09110                              RelationGetRelid(parent_rel),
09111                              inhseqno + 1,
09112                              catalogRelation);
09113 
09114     /* Now we're done with pg_inherits */
09115     heap_close(catalogRelation, RowExclusiveLock);
09116 
09117     /* keep our lock on the parent relation until commit */
09118     heap_close(parent_rel, NoLock);
09119 }
09120 
09121 /*
09122  * Obtain the source-text form of the constraint expression for a check
09123  * constraint, given its pg_constraint tuple
09124  */
09125 static char *
09126 decompile_conbin(HeapTuple contup, TupleDesc tupdesc)
09127 {
09128     Form_pg_constraint con;
09129     bool        isnull;
09130     Datum       attr;
09131     Datum       expr;
09132 
09133     con = (Form_pg_constraint) GETSTRUCT(contup);
09134     attr = heap_getattr(contup, Anum_pg_constraint_conbin, tupdesc, &isnull);
09135     if (isnull)
09136         elog(ERROR, "null conbin for constraint %u", HeapTupleGetOid(contup));
09137 
09138     expr = DirectFunctionCall2(pg_get_expr, attr,
09139                                ObjectIdGetDatum(con->conrelid));
09140     return TextDatumGetCString(expr);
09141 }
09142 
09143 /*
09144  * Determine whether two check constraints are functionally equivalent
09145  *
09146  * The test we apply is to see whether they reverse-compile to the same
09147  * source string.  This insulates us from issues like whether attributes
09148  * have the same physical column numbers in parent and child relations.
09149  */
09150 static bool
09151 constraints_equivalent(HeapTuple a, HeapTuple b, TupleDesc tupleDesc)
09152 {
09153     Form_pg_constraint acon = (Form_pg_constraint) GETSTRUCT(a);
09154     Form_pg_constraint bcon = (Form_pg_constraint) GETSTRUCT(b);
09155 
09156     if (acon->condeferrable != bcon->condeferrable ||
09157         acon->condeferred != bcon->condeferred ||
09158         strcmp(decompile_conbin(a, tupleDesc),
09159                decompile_conbin(b, tupleDesc)) != 0)
09160         return false;
09161     else
09162         return true;
09163 }
09164 
09165 /*
09166  * Check columns in child table match up with columns in parent, and increment
09167  * their attinhcount.
09168  *
09169  * Called by ATExecAddInherit
09170  *
09171  * Currently all parent columns must be found in child. Missing columns are an
09172  * error.  One day we might consider creating new columns like CREATE TABLE
09173  * does.  However, that is widely unpopular --- in the common use case of
09174  * partitioned tables it's a foot-gun.
09175  *
09176  * The data type must match exactly. If the parent column is NOT NULL then
09177  * the child must be as well. Defaults are not compared, however.
09178  */
09179 static void
09180 MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
09181 {
09182     Relation    attrrel;
09183     AttrNumber  parent_attno;
09184     int         parent_natts;
09185     TupleDesc   tupleDesc;
09186     HeapTuple   tuple;
09187 
09188     attrrel = heap_open(AttributeRelationId, RowExclusiveLock);
09189 
09190     tupleDesc = RelationGetDescr(parent_rel);
09191     parent_natts = tupleDesc->natts;
09192 
09193     for (parent_attno = 1; parent_attno <= parent_natts; parent_attno++)
09194     {
09195         Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
09196         char       *attributeName = NameStr(attribute->attname);
09197 
09198         /* Ignore dropped columns in the parent. */
09199         if (attribute->attisdropped)
09200             continue;
09201 
09202         /* Find same column in child (matching on column name). */
09203         tuple = SearchSysCacheCopyAttName(RelationGetRelid(child_rel),
09204                                           attributeName);
09205         if (HeapTupleIsValid(tuple))
09206         {
09207             /* Check they are same type, typmod, and collation */
09208             Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
09209 
09210             if (attribute->atttypid != childatt->atttypid ||
09211                 attribute->atttypmod != childatt->atttypmod)
09212                 ereport(ERROR,
09213                         (errcode(ERRCODE_DATATYPE_MISMATCH),
09214                          errmsg("child table \"%s\" has different type for column \"%s\"",
09215                                 RelationGetRelationName(child_rel),
09216                                 attributeName)));
09217 
09218             if (attribute->attcollation != childatt->attcollation)
09219                 ereport(ERROR,
09220                         (errcode(ERRCODE_COLLATION_MISMATCH),
09221                          errmsg("child table \"%s\" has different collation for column \"%s\"",
09222                                 RelationGetRelationName(child_rel),
09223                                 attributeName)));
09224 
09225             /*
09226              * Check child doesn't discard NOT NULL property.  (Other
09227              * constraints are checked elsewhere.)
09228              */
09229             if (attribute->attnotnull && !childatt->attnotnull)
09230                 ereport(ERROR,
09231                         (errcode(ERRCODE_DATATYPE_MISMATCH),
09232                 errmsg("column \"%s\" in child table must be marked NOT NULL",
09233                        attributeName)));
09234 
09235             /*
09236              * OK, bump the child column's inheritance count.  (If we fail
09237              * later on, this change will just roll back.)
09238              */
09239             childatt->attinhcount++;
09240             simple_heap_update(attrrel, &tuple->t_self, tuple);
09241             CatalogUpdateIndexes(attrrel, tuple);
09242             heap_freetuple(tuple);
09243         }
09244         else
09245         {
09246             ereport(ERROR,
09247                     (errcode(ERRCODE_DATATYPE_MISMATCH),
09248                      errmsg("child table is missing column \"%s\"",
09249                             attributeName)));
09250         }
09251     }
09252 
09253     heap_close(attrrel, RowExclusiveLock);
09254 }
09255 
09256 /*
09257  * Check constraints in child table match up with constraints in parent,
09258  * and increment their coninhcount.
09259  *
09260  * Constraints that are marked ONLY in the parent are ignored.
09261  *
09262  * Called by ATExecAddInherit
09263  *
09264  * Currently all constraints in parent must be present in the child. One day we
09265  * may consider adding new constraints like CREATE TABLE does.
09266  *
09267  * XXX This is O(N^2) which may be an issue with tables with hundreds of
09268  * constraints. As long as tables have more like 10 constraints it shouldn't be
09269  * a problem though. Even 100 constraints ought not be the end of the world.
09270  *
09271  * XXX See MergeWithExistingConstraint too if you change this code.
09272  */
09273 static void
09274 MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
09275 {
09276     Relation    catalog_relation;
09277     TupleDesc   tuple_desc;
09278     SysScanDesc parent_scan;
09279     ScanKeyData parent_key;
09280     HeapTuple   parent_tuple;
09281 
09282     catalog_relation = heap_open(ConstraintRelationId, RowExclusiveLock);
09283     tuple_desc = RelationGetDescr(catalog_relation);
09284 
09285     /* Outer loop scans through the parent's constraint definitions */
09286     ScanKeyInit(&parent_key,
09287                 Anum_pg_constraint_conrelid,
09288                 BTEqualStrategyNumber, F_OIDEQ,
09289                 ObjectIdGetDatum(RelationGetRelid(parent_rel)));
09290     parent_scan = systable_beginscan(catalog_relation, ConstraintRelidIndexId,
09291                                      true, SnapshotNow, 1, &parent_key);
09292 
09293     while (HeapTupleIsValid(parent_tuple = systable_getnext(parent_scan)))
09294     {
09295         Form_pg_constraint parent_con = (Form_pg_constraint) GETSTRUCT(parent_tuple);
09296         SysScanDesc child_scan;
09297         ScanKeyData child_key;
09298         HeapTuple   child_tuple;
09299         bool        found = false;
09300 
09301         if (parent_con->contype != CONSTRAINT_CHECK)
09302             continue;
09303 
09304         /* if the parent's constraint is marked NO INHERIT, it's not inherited */
09305         if (parent_con->connoinherit)
09306             continue;
09307 
09308         /* Search for a child constraint matching this one */
09309         ScanKeyInit(&child_key,
09310                     Anum_pg_constraint_conrelid,
09311                     BTEqualStrategyNumber, F_OIDEQ,
09312                     ObjectIdGetDatum(RelationGetRelid(child_rel)));
09313         child_scan = systable_beginscan(catalog_relation, ConstraintRelidIndexId,
09314                                         true, SnapshotNow, 1, &child_key);
09315 
09316         while (HeapTupleIsValid(child_tuple = systable_getnext(child_scan)))
09317         {
09318             Form_pg_constraint child_con = (Form_pg_constraint) GETSTRUCT(child_tuple);
09319             HeapTuple   child_copy;
09320 
09321             if (child_con->contype != CONSTRAINT_CHECK)
09322                 continue;
09323 
09324             if (strcmp(NameStr(parent_con->conname),
09325                        NameStr(child_con->conname)) != 0)
09326                 continue;
09327 
09328             if (!constraints_equivalent(parent_tuple, child_tuple, tuple_desc))
09329                 ereport(ERROR,
09330                         (errcode(ERRCODE_DATATYPE_MISMATCH),
09331                          errmsg("child table \"%s\" has different definition for check constraint \"%s\"",
09332                                 RelationGetRelationName(child_rel),
09333                                 NameStr(parent_con->conname))));
09334 
09335             /* If the constraint is "no inherit" then cannot merge */
09336             if (child_con->connoinherit)
09337                 ereport(ERROR,
09338                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
09339                          errmsg("constraint \"%s\" conflicts with non-inherited constraint on child table \"%s\"",
09340                                 NameStr(child_con->conname),
09341                                 RelationGetRelationName(child_rel))));
09342 
09343             /*
09344              * OK, bump the child constraint's inheritance count.  (If we fail
09345              * later on, this change will just roll back.)
09346              */
09347             child_copy = heap_copytuple(child_tuple);
09348             child_con = (Form_pg_constraint) GETSTRUCT(child_copy);
09349             child_con->coninhcount++;
09350             simple_heap_update(catalog_relation, &child_copy->t_self, child_copy);
09351             CatalogUpdateIndexes(catalog_relation, child_copy);
09352             heap_freetuple(child_copy);
09353 
09354             found = true;
09355             break;
09356         }
09357 
09358         systable_endscan(child_scan);
09359 
09360         if (!found)
09361             ereport(ERROR,
09362                     (errcode(ERRCODE_DATATYPE_MISMATCH),
09363                      errmsg("child table is missing constraint \"%s\"",
09364                             NameStr(parent_con->conname))));
09365     }
09366 
09367     systable_endscan(parent_scan);
09368     heap_close(catalog_relation, RowExclusiveLock);
09369 }
09370 
09371 /*
09372  * ALTER TABLE NO INHERIT
09373  *
09374  * Drop a parent from the child's parents. This just adjusts the attinhcount
09375  * and attislocal of the columns and removes the pg_inherit and pg_depend
09376  * entries.
09377  *
09378  * If attinhcount goes to 0 then attislocal gets set to true. If it goes back
09379  * up attislocal stays true, which means if a child is ever removed from a
09380  * parent then its columns will never be automatically dropped which may
09381  * surprise. But at least we'll never surprise by dropping columns someone
09382  * isn't expecting to be dropped which would actually mean data loss.
09383  *
09384  * coninhcount and conislocal for inherited constraints are adjusted in
09385  * exactly the same way.
09386  */
09387 static void
09388 ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
09389 {
09390     Relation    parent_rel;
09391     Relation    catalogRelation;
09392     SysScanDesc scan;
09393     ScanKeyData key[3];
09394     HeapTuple   inheritsTuple,
09395                 attributeTuple,
09396                 constraintTuple;
09397     List       *connames;
09398     bool        found = false;
09399 
09400     /*
09401      * AccessShareLock on the parent is probably enough, seeing that DROP
09402      * TABLE doesn't lock parent tables at all.  We need some lock since we'll
09403      * be inspecting the parent's schema.
09404      */
09405     parent_rel = heap_openrv(parent, AccessShareLock);
09406 
09407     /*
09408      * We don't bother to check ownership of the parent table --- ownership of
09409      * the child is presumed enough rights.
09410      */
09411 
09412     /*
09413      * Find and destroy the pg_inherits entry linking the two, or error out if
09414      * there is none.
09415      */
09416     catalogRelation = heap_open(InheritsRelationId, RowExclusiveLock);
09417     ScanKeyInit(&key[0],
09418                 Anum_pg_inherits_inhrelid,
09419                 BTEqualStrategyNumber, F_OIDEQ,
09420                 ObjectIdGetDatum(RelationGetRelid(rel)));
09421     scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndexId,
09422                               true, SnapshotNow, 1, key);
09423 
09424     while (HeapTupleIsValid(inheritsTuple = systable_getnext(scan)))
09425     {
09426         Oid         inhparent;
09427 
09428         inhparent = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhparent;
09429         if (inhparent == RelationGetRelid(parent_rel))
09430         {
09431             simple_heap_delete(catalogRelation, &inheritsTuple->t_self);
09432             found = true;
09433             break;
09434         }
09435     }
09436 
09437     systable_endscan(scan);
09438     heap_close(catalogRelation, RowExclusiveLock);
09439 
09440     if (!found)
09441         ereport(ERROR,
09442                 (errcode(ERRCODE_UNDEFINED_TABLE),
09443                  errmsg("relation \"%s\" is not a parent of relation \"%s\"",
09444                         RelationGetRelationName(parent_rel),
09445                         RelationGetRelationName(rel))));
09446 
09447     /*
09448      * Search through child columns looking for ones matching parent rel
09449      */
09450     catalogRelation = heap_open(AttributeRelationId, RowExclusiveLock);
09451     ScanKeyInit(&key[0],
09452                 Anum_pg_attribute_attrelid,
09453                 BTEqualStrategyNumber, F_OIDEQ,
09454                 ObjectIdGetDatum(RelationGetRelid(rel)));
09455     scan = systable_beginscan(catalogRelation, AttributeRelidNumIndexId,
09456                               true, SnapshotNow, 1, key);
09457     while (HeapTupleIsValid(attributeTuple = systable_getnext(scan)))
09458     {
09459         Form_pg_attribute att = (Form_pg_attribute) GETSTRUCT(attributeTuple);
09460 
09461         /* Ignore if dropped or not inherited */
09462         if (att->attisdropped)
09463             continue;
09464         if (att->attinhcount <= 0)
09465             continue;
09466 
09467         if (SearchSysCacheExistsAttName(RelationGetRelid(parent_rel),
09468                                         NameStr(att->attname)))
09469         {
09470             /* Decrement inhcount and possibly set islocal to true */
09471             HeapTuple   copyTuple = heap_copytuple(attributeTuple);
09472             Form_pg_attribute copy_att = (Form_pg_attribute) GETSTRUCT(copyTuple);
09473 
09474             copy_att->attinhcount--;
09475             if (copy_att->attinhcount == 0)
09476                 copy_att->attislocal = true;
09477 
09478             simple_heap_update(catalogRelation, &copyTuple->t_self, copyTuple);
09479             CatalogUpdateIndexes(catalogRelation, copyTuple);
09480             heap_freetuple(copyTuple);
09481         }
09482     }
09483     systable_endscan(scan);
09484     heap_close(catalogRelation, RowExclusiveLock);
09485 
09486     /*
09487      * Likewise, find inherited check constraints and disinherit them. To do
09488      * this, we first need a list of the names of the parent's check
09489      * constraints.  (We cheat a bit by only checking for name matches,
09490      * assuming that the expressions will match.)
09491      */
09492     catalogRelation = heap_open(ConstraintRelationId, RowExclusiveLock);
09493     ScanKeyInit(&key[0],
09494                 Anum_pg_constraint_conrelid,
09495                 BTEqualStrategyNumber, F_OIDEQ,
09496                 ObjectIdGetDatum(RelationGetRelid(parent_rel)));
09497     scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
09498                               true, SnapshotNow, 1, key);
09499 
09500     connames = NIL;
09501 
09502     while (HeapTupleIsValid(constraintTuple = systable_getnext(scan)))
09503     {
09504         Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTuple);
09505 
09506         if (con->contype == CONSTRAINT_CHECK)
09507             connames = lappend(connames, pstrdup(NameStr(con->conname)));
09508     }
09509 
09510     systable_endscan(scan);
09511 
09512     /* Now scan the child's constraints */
09513     ScanKeyInit(&key[0],
09514                 Anum_pg_constraint_conrelid,
09515                 BTEqualStrategyNumber, F_OIDEQ,
09516                 ObjectIdGetDatum(RelationGetRelid(rel)));
09517     scan = systable_beginscan(catalogRelation, ConstraintRelidIndexId,
09518                               true, SnapshotNow, 1, key);
09519 
09520     while (HeapTupleIsValid(constraintTuple = systable_getnext(scan)))
09521     {
09522         Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(constraintTuple);
09523         bool        match;
09524         ListCell   *lc;
09525 
09526         if (con->contype != CONSTRAINT_CHECK)
09527             continue;
09528 
09529         match = false;
09530         foreach(lc, connames)
09531         {
09532             if (strcmp(NameStr(con->conname), (char *) lfirst(lc)) == 0)
09533             {
09534                 match = true;
09535                 break;
09536             }
09537         }
09538 
09539         if (match)
09540         {
09541             /* Decrement inhcount and possibly set islocal to true */
09542             HeapTuple   copyTuple = heap_copytuple(constraintTuple);
09543             Form_pg_constraint copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
09544 
09545             if (copy_con->coninhcount <= 0)     /* shouldn't happen */
09546                 elog(ERROR, "relation %u has non-inherited constraint \"%s\"",
09547                      RelationGetRelid(rel), NameStr(copy_con->conname));
09548 
09549             copy_con->coninhcount--;
09550             if (copy_con->coninhcount == 0)
09551                 copy_con->conislocal = true;
09552 
09553             simple_heap_update(catalogRelation, &copyTuple->t_self, copyTuple);
09554             CatalogUpdateIndexes(catalogRelation, copyTuple);
09555             heap_freetuple(copyTuple);
09556         }
09557     }
09558 
09559     systable_endscan(scan);
09560     heap_close(catalogRelation, RowExclusiveLock);
09561 
09562     drop_parent_dependency(RelationGetRelid(rel),
09563                            RelationRelationId,
09564                            RelationGetRelid(parent_rel));
09565 
09566     /*
09567      * Post alter hook of this inherits. Since object_access_hook doesn't
09568      * take multiple object identifiers, we relay oid of parent relation
09569      * using auxiliary_id argument.
09570      */
09571     InvokeObjectPostAlterHookArg(InheritsRelationId,
09572                                  RelationGetRelid(rel), 0,
09573                                  RelationGetRelid(parent_rel), false);
09574 
09575     /* keep our lock on the parent relation until commit */
09576     heap_close(parent_rel, NoLock);
09577 }
09578 
09579 /*
09580  * Drop the dependency created by StoreCatalogInheritance1 (CREATE TABLE
09581  * INHERITS/ALTER TABLE INHERIT -- refclassid will be RelationRelationId) or
09582  * heap_create_with_catalog (CREATE TABLE OF/ALTER TABLE OF -- refclassid will
09583  * be TypeRelationId).  There's no convenient way to do this, so go trawling
09584  * through pg_depend.
09585  */
09586 static void
09587 drop_parent_dependency(Oid relid, Oid refclassid, Oid refobjid)
09588 {
09589     Relation    catalogRelation;
09590     SysScanDesc scan;
09591     ScanKeyData key[3];
09592     HeapTuple   depTuple;
09593 
09594     catalogRelation = heap_open(DependRelationId, RowExclusiveLock);
09595 
09596     ScanKeyInit(&key[0],
09597                 Anum_pg_depend_classid,
09598                 BTEqualStrategyNumber, F_OIDEQ,
09599                 ObjectIdGetDatum(RelationRelationId));
09600     ScanKeyInit(&key[1],
09601                 Anum_pg_depend_objid,
09602                 BTEqualStrategyNumber, F_OIDEQ,
09603                 ObjectIdGetDatum(relid));
09604     ScanKeyInit(&key[2],
09605                 Anum_pg_depend_objsubid,
09606                 BTEqualStrategyNumber, F_INT4EQ,
09607                 Int32GetDatum(0));
09608 
09609     scan = systable_beginscan(catalogRelation, DependDependerIndexId, true,
09610                               SnapshotNow, 3, key);
09611 
09612     while (HeapTupleIsValid(depTuple = systable_getnext(scan)))
09613     {
09614         Form_pg_depend dep = (Form_pg_depend) GETSTRUCT(depTuple);
09615 
09616         if (dep->refclassid == refclassid &&
09617             dep->refobjid == refobjid &&
09618             dep->refobjsubid == 0 &&
09619             dep->deptype == DEPENDENCY_NORMAL)
09620             simple_heap_delete(catalogRelation, &depTuple->t_self);
09621     }
09622 
09623     systable_endscan(scan);
09624     heap_close(catalogRelation, RowExclusiveLock);
09625 }
09626 
09627 /*
09628  * ALTER TABLE OF
09629  *
09630  * Attach a table to a composite type, as though it had been created with CREATE
09631  * TABLE OF.  All attname, atttypid, atttypmod and attcollation must match.  The
09632  * subject table must not have inheritance parents.  These restrictions ensure
09633  * that you cannot create a configuration impossible with CREATE TABLE OF alone.
09634  */
09635 static void
09636 ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
09637 {
09638     Oid         relid = RelationGetRelid(rel);
09639     Type        typetuple;
09640     Oid         typeid;
09641     Relation    inheritsRelation,
09642                 relationRelation;
09643     SysScanDesc scan;
09644     ScanKeyData key;
09645     AttrNumber  table_attno,
09646                 type_attno;
09647     TupleDesc   typeTupleDesc,
09648                 tableTupleDesc;
09649     ObjectAddress tableobj,
09650                 typeobj;
09651     HeapTuple   classtuple;
09652 
09653     /* Validate the type. */
09654     typetuple = typenameType(NULL, ofTypename, NULL);
09655     check_of_type(typetuple);
09656     typeid = HeapTupleGetOid(typetuple);
09657 
09658     /* Fail if the table has any inheritance parents. */
09659     inheritsRelation = heap_open(InheritsRelationId, AccessShareLock);
09660     ScanKeyInit(&key,
09661                 Anum_pg_inherits_inhrelid,
09662                 BTEqualStrategyNumber, F_OIDEQ,
09663                 ObjectIdGetDatum(relid));
09664     scan = systable_beginscan(inheritsRelation, InheritsRelidSeqnoIndexId,
09665                               true, SnapshotNow, 1, &key);
09666     if (HeapTupleIsValid(systable_getnext(scan)))
09667         ereport(ERROR,
09668                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
09669                  errmsg("typed tables cannot inherit")));
09670     systable_endscan(scan);
09671     heap_close(inheritsRelation, AccessShareLock);
09672 
09673     /*
09674      * Check the tuple descriptors for compatibility.  Unlike inheritance, we
09675      * require that the order also match.  However, attnotnull need not match.
09676      * Also unlike inheritance, we do not require matching relhasoids.
09677      */
09678     typeTupleDesc = lookup_rowtype_tupdesc(typeid, -1);
09679     tableTupleDesc = RelationGetDescr(rel);
09680     table_attno = 1;
09681     for (type_attno = 1; type_attno <= typeTupleDesc->natts; type_attno++)
09682     {
09683         Form_pg_attribute type_attr,
09684                     table_attr;
09685         const char *type_attname,
09686                    *table_attname;
09687 
09688         /* Get the next non-dropped type attribute. */
09689         type_attr = typeTupleDesc->attrs[type_attno - 1];
09690         if (type_attr->attisdropped)
09691             continue;
09692         type_attname = NameStr(type_attr->attname);
09693 
09694         /* Get the next non-dropped table attribute. */
09695         do
09696         {
09697             if (table_attno > tableTupleDesc->natts)
09698                 ereport(ERROR,
09699                         (errcode(ERRCODE_DATATYPE_MISMATCH),
09700                          errmsg("table is missing column \"%s\"",
09701                                 type_attname)));
09702             table_attr = tableTupleDesc->attrs[table_attno++ - 1];
09703         } while (table_attr->attisdropped);
09704         table_attname = NameStr(table_attr->attname);
09705 
09706         /* Compare name. */
09707         if (strncmp(table_attname, type_attname, NAMEDATALEN) != 0)
09708             ereport(ERROR,
09709                     (errcode(ERRCODE_DATATYPE_MISMATCH),
09710                  errmsg("table has column \"%s\" where type requires \"%s\"",
09711                         table_attname, type_attname)));
09712 
09713         /* Compare type. */
09714         if (table_attr->atttypid != type_attr->atttypid ||
09715             table_attr->atttypmod != type_attr->atttypmod ||
09716             table_attr->attcollation != type_attr->attcollation)
09717             ereport(ERROR,
09718                     (errcode(ERRCODE_DATATYPE_MISMATCH),
09719                   errmsg("table \"%s\" has different type for column \"%s\"",
09720                          RelationGetRelationName(rel), type_attname)));
09721     }
09722     DecrTupleDescRefCount(typeTupleDesc);
09723 
09724     /* Any remaining columns at the end of the table had better be dropped. */
09725     for (; table_attno <= tableTupleDesc->natts; table_attno++)
09726     {
09727         Form_pg_attribute table_attr = tableTupleDesc->attrs[table_attno - 1];
09728 
09729         if (!table_attr->attisdropped)
09730             ereport(ERROR,
09731                     (errcode(ERRCODE_DATATYPE_MISMATCH),
09732                      errmsg("table has extra column \"%s\"",
09733                             NameStr(table_attr->attname))));
09734     }
09735 
09736     /* If the table was already typed, drop the existing dependency. */
09737     if (rel->rd_rel->reloftype)
09738         drop_parent_dependency(relid, TypeRelationId, rel->rd_rel->reloftype);
09739 
09740     /* Record a dependency on the new type. */
09741     tableobj.classId = RelationRelationId;
09742     tableobj.objectId = relid;
09743     tableobj.objectSubId = 0;
09744     typeobj.classId = TypeRelationId;
09745     typeobj.objectId = typeid;
09746     typeobj.objectSubId = 0;
09747     recordDependencyOn(&tableobj, &typeobj, DEPENDENCY_NORMAL);
09748 
09749     /* Update pg_class.reloftype */
09750     relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
09751     classtuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
09752     if (!HeapTupleIsValid(classtuple))
09753         elog(ERROR, "cache lookup failed for relation %u", relid);
09754     ((Form_pg_class) GETSTRUCT(classtuple))->reloftype = typeid;
09755     simple_heap_update(relationRelation, &classtuple->t_self, classtuple);
09756     CatalogUpdateIndexes(relationRelation, classtuple);
09757 
09758     InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
09759 
09760     heap_freetuple(classtuple);
09761     heap_close(relationRelation, RowExclusiveLock);
09762 
09763     ReleaseSysCache(typetuple);
09764 }
09765 
09766 /*
09767  * ALTER TABLE NOT OF
09768  *
09769  * Detach a typed table from its originating type.  Just clear reloftype and
09770  * remove the dependency.
09771  */
09772 static void
09773 ATExecDropOf(Relation rel, LOCKMODE lockmode)
09774 {
09775     Oid         relid = RelationGetRelid(rel);
09776     Relation    relationRelation;
09777     HeapTuple   tuple;
09778 
09779     if (!OidIsValid(rel->rd_rel->reloftype))
09780         ereport(ERROR,
09781                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
09782                  errmsg("\"%s\" is not a typed table",
09783                         RelationGetRelationName(rel))));
09784 
09785     /*
09786      * We don't bother to check ownership of the type --- ownership of the
09787      * table is presumed enough rights.  No lock required on the type, either.
09788      */
09789 
09790     drop_parent_dependency(relid, TypeRelationId, rel->rd_rel->reloftype);
09791 
09792     /* Clear pg_class.reloftype */
09793     relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
09794     tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
09795     if (!HeapTupleIsValid(tuple))
09796         elog(ERROR, "cache lookup failed for relation %u", relid);
09797     ((Form_pg_class) GETSTRUCT(tuple))->reloftype = InvalidOid;
09798     simple_heap_update(relationRelation, &tuple->t_self, tuple);
09799     CatalogUpdateIndexes(relationRelation, tuple);
09800 
09801     InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
09802 
09803     heap_freetuple(tuple);
09804     heap_close(relationRelation, RowExclusiveLock);
09805 }
09806 
09807 /*
09808  * ALTER FOREIGN TABLE <name> OPTIONS (...)
09809  */
09810 static void
09811 ATExecGenericOptions(Relation rel, List *options)
09812 {
09813     Relation    ftrel;
09814     ForeignServer *server;
09815     ForeignDataWrapper *fdw;
09816     HeapTuple   tuple;
09817     bool        isnull;
09818     Datum       repl_val[Natts_pg_foreign_table];
09819     bool        repl_null[Natts_pg_foreign_table];
09820     bool        repl_repl[Natts_pg_foreign_table];
09821     Datum       datum;
09822     Form_pg_foreign_table tableform;
09823 
09824     if (options == NIL)
09825         return;
09826 
09827     ftrel = heap_open(ForeignTableRelationId, RowExclusiveLock);
09828 
09829     tuple = SearchSysCacheCopy1(FOREIGNTABLEREL, rel->rd_id);
09830     if (!HeapTupleIsValid(tuple))
09831         ereport(ERROR,
09832                 (errcode(ERRCODE_UNDEFINED_OBJECT),
09833                  errmsg("foreign table \"%s\" does not exist",
09834                         RelationGetRelationName(rel))));
09835     tableform = (Form_pg_foreign_table) GETSTRUCT(tuple);
09836     server = GetForeignServer(tableform->ftserver);
09837     fdw = GetForeignDataWrapper(server->fdwid);
09838 
09839     memset(repl_val, 0, sizeof(repl_val));
09840     memset(repl_null, false, sizeof(repl_null));
09841     memset(repl_repl, false, sizeof(repl_repl));
09842 
09843     /* Extract the current options */
09844     datum = SysCacheGetAttr(FOREIGNTABLEREL,
09845                             tuple,
09846                             Anum_pg_foreign_table_ftoptions,
09847                             &isnull);
09848     if (isnull)
09849         datum = PointerGetDatum(NULL);
09850 
09851     /* Transform the options */
09852     datum = transformGenericOptions(ForeignTableRelationId,
09853                                     datum,
09854                                     options,
09855                                     fdw->fdwvalidator);
09856 
09857     if (PointerIsValid(DatumGetPointer(datum)))
09858         repl_val[Anum_pg_foreign_table_ftoptions - 1] = datum;
09859     else
09860         repl_null[Anum_pg_foreign_table_ftoptions - 1] = true;
09861 
09862     repl_repl[Anum_pg_foreign_table_ftoptions - 1] = true;
09863 
09864     /* Everything looks good - update the tuple */
09865 
09866     tuple = heap_modify_tuple(tuple, RelationGetDescr(ftrel),
09867                               repl_val, repl_null, repl_repl);
09868 
09869     simple_heap_update(ftrel, &tuple->t_self, tuple);
09870     CatalogUpdateIndexes(ftrel, tuple);
09871 
09872     InvokeObjectPostAlterHook(ForeignTableRelationId,
09873                               RelationGetRelid(rel), 0);
09874 
09875     heap_close(ftrel, RowExclusiveLock);
09876 
09877     heap_freetuple(tuple);
09878 }
09879 
09880 /*
09881  * Execute ALTER TABLE SET SCHEMA
09882  */
09883 Oid
09884 AlterTableNamespace(AlterObjectSchemaStmt *stmt)
09885 {
09886     Relation    rel;
09887     Oid         relid;
09888     Oid         oldNspOid;
09889     Oid         nspOid;
09890     RangeVar   *newrv;
09891     ObjectAddresses *objsMoved;
09892 
09893     relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
09894                                      stmt->missing_ok, false,
09895                                      RangeVarCallbackForAlterRelation,
09896                                      (void *) stmt);
09897 
09898     if (!OidIsValid(relid))
09899     {
09900         ereport(NOTICE,
09901                 (errmsg("relation \"%s\" does not exist, skipping",
09902                         stmt->relation->relname)));
09903         return InvalidOid;
09904     }
09905 
09906     rel = relation_open(relid, NoLock);
09907 
09908     oldNspOid = RelationGetNamespace(rel);
09909 
09910     /* If it's an owned sequence, disallow moving it by itself. */
09911     if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
09912     {
09913         Oid         tableId;
09914         int32       colId;
09915 
09916         if (sequenceIsOwned(relid, &tableId, &colId))
09917             ereport(ERROR,
09918                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
09919                  errmsg("cannot move an owned sequence into another schema"),
09920                      errdetail("Sequence \"%s\" is linked to table \"%s\".",
09921                                RelationGetRelationName(rel),
09922                                get_rel_name(tableId))));
09923     }
09924 
09925     /* Get and lock schema OID and check its permissions. */
09926     newrv = makeRangeVar(stmt->newschema, RelationGetRelationName(rel), -1);
09927     nspOid = RangeVarGetAndCheckCreationNamespace(newrv, NoLock, NULL);
09928 
09929     /* common checks on switching namespaces */
09930     CheckSetNamespace(oldNspOid, nspOid, RelationRelationId, relid);
09931 
09932     objsMoved = new_object_addresses();
09933     AlterTableNamespaceInternal(rel, oldNspOid, nspOid, objsMoved);
09934     free_object_addresses(objsMoved);
09935 
09936     /* close rel, but keep lock until commit */
09937     relation_close(rel, NoLock);
09938 
09939     return relid;
09940 }
09941 
09942 /*
09943  * The guts of relocating a table or materialized view to another namespace:
09944  * besides moving the relation itself, its dependent objects are relocated to
09945  * the new schema.
09946  */
09947 void
09948 AlterTableNamespaceInternal(Relation rel, Oid oldNspOid, Oid nspOid,
09949                             ObjectAddresses *objsMoved)
09950 {
09951     Relation    classRel;
09952 
09953     Assert(objsMoved != NULL);
09954 
09955     /* OK, modify the pg_class row and pg_depend entry */
09956     classRel = heap_open(RelationRelationId, RowExclusiveLock);
09957 
09958     AlterRelationNamespaceInternal(classRel, RelationGetRelid(rel), oldNspOid,
09959                                    nspOid, true, objsMoved);
09960 
09961     /* Fix the table's row type too */
09962     AlterTypeNamespaceInternal(rel->rd_rel->reltype,
09963                                nspOid, false, false, objsMoved);
09964 
09965     /* Fix other dependent stuff */
09966     if (rel->rd_rel->relkind == RELKIND_RELATION ||
09967         rel->rd_rel->relkind == RELKIND_MATVIEW)
09968     {
09969         AlterIndexNamespaces(classRel, rel, oldNspOid, nspOid, objsMoved);
09970         AlterSeqNamespaces(classRel, rel, oldNspOid, nspOid,
09971                            objsMoved, AccessExclusiveLock);
09972         AlterConstraintNamespaces(RelationGetRelid(rel), oldNspOid, nspOid,
09973                                   false, objsMoved);
09974     }
09975 
09976     heap_close(classRel, RowExclusiveLock);
09977 }
09978 
09979 /*
09980  * The guts of relocating a relation to another namespace: fix the pg_class
09981  * entry, and the pg_depend entry if any.  Caller must already have
09982  * opened and write-locked pg_class.
09983  */
09984 void
09985 AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
09986                                Oid oldNspOid, Oid newNspOid,
09987                                bool hasDependEntry, ObjectAddresses *objsMoved)
09988 {
09989     HeapTuple   classTup;
09990     Form_pg_class classForm;
09991     ObjectAddress   thisobj;
09992 
09993     classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relOid));
09994     if (!HeapTupleIsValid(classTup))
09995         elog(ERROR, "cache lookup failed for relation %u", relOid);
09996     classForm = (Form_pg_class) GETSTRUCT(classTup);
09997 
09998     Assert(classForm->relnamespace == oldNspOid);
09999 
10000     thisobj.classId = RelationRelationId;
10001     thisobj.objectId = relOid;
10002     thisobj.objectSubId = 0;
10003 
10004     /*
10005      * Do nothing when there's nothing to do.
10006      */
10007     if (!object_address_present(&thisobj, objsMoved))
10008     {
10009         /* check for duplicate name (more friendly than unique-index failure) */
10010         if (get_relname_relid(NameStr(classForm->relname),
10011                               newNspOid) != InvalidOid)
10012             ereport(ERROR,
10013                     (errcode(ERRCODE_DUPLICATE_TABLE),
10014                      errmsg("relation \"%s\" already exists in schema \"%s\"",
10015                             NameStr(classForm->relname),
10016                             get_namespace_name(newNspOid))));
10017 
10018         /* classTup is a copy, so OK to scribble on */
10019         classForm->relnamespace = newNspOid;
10020 
10021         simple_heap_update(classRel, &classTup->t_self, classTup);
10022         CatalogUpdateIndexes(classRel, classTup);
10023 
10024         /* Update dependency on schema if caller said so */
10025         if (hasDependEntry &&
10026             changeDependencyFor(RelationRelationId, relOid,
10027                                 NamespaceRelationId, oldNspOid, newNspOid) != 1)
10028             elog(ERROR, "failed to change schema dependency for relation \"%s\"",
10029                  NameStr(classForm->relname));
10030 
10031         add_exact_object_address(&thisobj, objsMoved);
10032 
10033         InvokeObjectPostAlterHook(RelationRelationId, relOid, 0);
10034     }
10035 
10036     heap_freetuple(classTup);
10037 }
10038 
10039 /*
10040  * Move all indexes for the specified relation to another namespace.
10041  *
10042  * Note: we assume adequate permission checking was done by the caller,
10043  * and that the caller has a suitable lock on the owning relation.
10044  */
10045 static void
10046 AlterIndexNamespaces(Relation classRel, Relation rel,
10047                      Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved)
10048 {
10049     List       *indexList;
10050     ListCell   *l;
10051 
10052     indexList = RelationGetIndexList(rel);
10053 
10054     foreach(l, indexList)
10055     {
10056         Oid         indexOid = lfirst_oid(l);
10057         ObjectAddress thisobj;
10058 
10059         thisobj.classId = RelationRelationId;
10060         thisobj.objectId = indexOid;
10061         thisobj.objectSubId = 0;
10062 
10063         /*
10064          * Note: currently, the index will not have its own dependency on the
10065          * namespace, so we don't need to do changeDependencyFor(). There's no
10066          * row type in pg_type, either.
10067          *
10068          * XXX this objsMoved test may be pointless -- surely we have a single
10069          * dependency link from a relation to each index?
10070          */
10071         if (!object_address_present(&thisobj, objsMoved))
10072         {
10073             AlterRelationNamespaceInternal(classRel, indexOid,
10074                                            oldNspOid, newNspOid,
10075                                            false, objsMoved);
10076             add_exact_object_address(&thisobj, objsMoved);
10077         }
10078     }
10079 
10080     list_free(indexList);
10081 }
10082 
10083 /*
10084  * Move all SERIAL-column sequences of the specified relation to another
10085  * namespace.
10086  *
10087  * Note: we assume adequate permission checking was done by the caller,
10088  * and that the caller has a suitable lock on the owning relation.
10089  */
10090 static void
10091 AlterSeqNamespaces(Relation classRel, Relation rel,
10092                    Oid oldNspOid, Oid newNspOid, ObjectAddresses *objsMoved,
10093                    LOCKMODE lockmode)
10094 {
10095     Relation    depRel;
10096     SysScanDesc scan;
10097     ScanKeyData key[2];
10098     HeapTuple   tup;
10099 
10100     /*
10101      * SERIAL sequences are those having an auto dependency on one of the
10102      * table's columns (we don't care *which* column, exactly).
10103      */
10104     depRel = heap_open(DependRelationId, AccessShareLock);
10105 
10106     ScanKeyInit(&key[0],
10107                 Anum_pg_depend_refclassid,
10108                 BTEqualStrategyNumber, F_OIDEQ,
10109                 ObjectIdGetDatum(RelationRelationId));
10110     ScanKeyInit(&key[1],
10111                 Anum_pg_depend_refobjid,
10112                 BTEqualStrategyNumber, F_OIDEQ,
10113                 ObjectIdGetDatum(RelationGetRelid(rel)));
10114     /* we leave refobjsubid unspecified */
10115 
10116     scan = systable_beginscan(depRel, DependReferenceIndexId, true,
10117                               SnapshotNow, 2, key);
10118 
10119     while (HeapTupleIsValid(tup = systable_getnext(scan)))
10120     {
10121         Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
10122         Relation    seqRel;
10123 
10124         /* skip dependencies other than auto dependencies on columns */
10125         if (depForm->refobjsubid == 0 ||
10126             depForm->classid != RelationRelationId ||
10127             depForm->objsubid != 0 ||
10128             depForm->deptype != DEPENDENCY_AUTO)
10129             continue;
10130 
10131         /* Use relation_open just in case it's an index */
10132         seqRel = relation_open(depForm->objid, lockmode);
10133 
10134         /* skip non-sequence relations */
10135         if (RelationGetForm(seqRel)->relkind != RELKIND_SEQUENCE)
10136         {
10137             /* No need to keep the lock */
10138             relation_close(seqRel, lockmode);
10139             continue;
10140         }
10141 
10142         /* Fix the pg_class and pg_depend entries */
10143         AlterRelationNamespaceInternal(classRel, depForm->objid,
10144                                        oldNspOid, newNspOid,
10145                                        true, objsMoved);
10146 
10147         /*
10148          * Sequences have entries in pg_type. We need to be careful to move
10149          * them to the new namespace, too.
10150          */
10151         AlterTypeNamespaceInternal(RelationGetForm(seqRel)->reltype,
10152                                    newNspOid, false, false, objsMoved);
10153 
10154         /* Now we can close it.  Keep the lock till end of transaction. */
10155         relation_close(seqRel, NoLock);
10156     }
10157 
10158     systable_endscan(scan);
10159 
10160     relation_close(depRel, AccessShareLock);
10161 }
10162 
10163 
10164 /*
10165  * This code supports
10166  *  CREATE TEMP TABLE ... ON COMMIT { DROP | PRESERVE ROWS | DELETE ROWS }
10167  *
10168  * Because we only support this for TEMP tables, it's sufficient to remember
10169  * the state in a backend-local data structure.
10170  */
10171 
10172 /*
10173  * Register a newly-created relation's ON COMMIT action.
10174  */
10175 void
10176 register_on_commit_action(Oid relid, OnCommitAction action)
10177 {
10178     OnCommitItem *oc;
10179     MemoryContext oldcxt;
10180 
10181     /*
10182      * We needn't bother registering the relation unless there is an ON COMMIT
10183      * action we need to take.
10184      */
10185     if (action == ONCOMMIT_NOOP || action == ONCOMMIT_PRESERVE_ROWS)
10186         return;
10187 
10188     oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
10189 
10190     oc = (OnCommitItem *) palloc(sizeof(OnCommitItem));
10191     oc->relid = relid;
10192     oc->oncommit = action;
10193     oc->creating_subid = GetCurrentSubTransactionId();
10194     oc->deleting_subid = InvalidSubTransactionId;
10195 
10196     on_commits = lcons(oc, on_commits);
10197 
10198     MemoryContextSwitchTo(oldcxt);
10199 }
10200 
10201 /*
10202  * Unregister any ON COMMIT action when a relation is deleted.
10203  *
10204  * Actually, we only mark the OnCommitItem entry as to be deleted after commit.
10205  */
10206 void
10207 remove_on_commit_action(Oid relid)
10208 {
10209     ListCell   *l;
10210 
10211     foreach(l, on_commits)
10212     {
10213         OnCommitItem *oc = (OnCommitItem *) lfirst(l);
10214 
10215         if (oc->relid == relid)
10216         {
10217             oc->deleting_subid = GetCurrentSubTransactionId();
10218             break;
10219         }
10220     }
10221 }
10222 
10223 /*
10224  * Perform ON COMMIT actions.
10225  *
10226  * This is invoked just before actually committing, since it's possible
10227  * to encounter errors.
10228  */
10229 void
10230 PreCommit_on_commit_actions(void)
10231 {
10232     ListCell   *l;
10233     List       *oids_to_truncate = NIL;
10234 
10235     foreach(l, on_commits)
10236     {
10237         OnCommitItem *oc = (OnCommitItem *) lfirst(l);
10238 
10239         /* Ignore entry if already dropped in this xact */
10240         if (oc->deleting_subid != InvalidSubTransactionId)
10241             continue;
10242 
10243         switch (oc->oncommit)
10244         {
10245             case ONCOMMIT_NOOP:
10246             case ONCOMMIT_PRESERVE_ROWS:
10247                 /* Do nothing (there shouldn't be such entries, actually) */
10248                 break;
10249             case ONCOMMIT_DELETE_ROWS:
10250                 /*
10251                  * If this transaction hasn't accessed any temporary
10252                  * relations, we can skip truncating ON COMMIT DELETE ROWS
10253                  * tables, as they must still be empty.
10254                  */
10255                 if (MyXactAccessedTempRel)
10256                     oids_to_truncate = lappend_oid(oids_to_truncate, oc->relid);
10257                 break;
10258             case ONCOMMIT_DROP:
10259                 {
10260                     ObjectAddress object;
10261 
10262                     object.classId = RelationRelationId;
10263                     object.objectId = oc->relid;
10264                     object.objectSubId = 0;
10265 
10266                     /*
10267                      * Since this is an automatic drop, rather than one
10268                      * directly initiated by the user, we pass the
10269                      * PERFORM_DELETION_INTERNAL flag.
10270                      */
10271                     performDeletion(&object,
10272                                     DROP_CASCADE, PERFORM_DELETION_INTERNAL);
10273 
10274                     /*
10275                      * Note that table deletion will call
10276                      * remove_on_commit_action, so the entry should get marked
10277                      * as deleted.
10278                      */
10279                     Assert(oc->deleting_subid != InvalidSubTransactionId);
10280                     break;
10281                 }
10282         }
10283     }
10284     if (oids_to_truncate != NIL)
10285     {
10286         heap_truncate(oids_to_truncate);
10287         CommandCounterIncrement();      /* XXX needed? */
10288     }
10289 }
10290 
10291 /*
10292  * Post-commit or post-abort cleanup for ON COMMIT management.
10293  *
10294  * All we do here is remove no-longer-needed OnCommitItem entries.
10295  *
10296  * During commit, remove entries that were deleted during this transaction;
10297  * during abort, remove those created during this transaction.
10298  */
10299 void
10300 AtEOXact_on_commit_actions(bool isCommit)
10301 {
10302     ListCell   *cur_item;
10303     ListCell   *prev_item;
10304 
10305     prev_item = NULL;
10306     cur_item = list_head(on_commits);
10307 
10308     while (cur_item != NULL)
10309     {
10310         OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
10311 
10312         if (isCommit ? oc->deleting_subid != InvalidSubTransactionId :
10313             oc->creating_subid != InvalidSubTransactionId)
10314         {
10315             /* cur_item must be removed */
10316             on_commits = list_delete_cell(on_commits, cur_item, prev_item);
10317             pfree(oc);
10318             if (prev_item)
10319                 cur_item = lnext(prev_item);
10320             else
10321                 cur_item = list_head(on_commits);
10322         }
10323         else
10324         {
10325             /* cur_item must be preserved */
10326             oc->creating_subid = InvalidSubTransactionId;
10327             oc->deleting_subid = InvalidSubTransactionId;
10328             prev_item = cur_item;
10329             cur_item = lnext(prev_item);
10330         }
10331     }
10332 }
10333 
10334 /*
10335  * Post-subcommit or post-subabort cleanup for ON COMMIT management.
10336  *
10337  * During subabort, we can immediately remove entries created during this
10338  * subtransaction.  During subcommit, just relabel entries marked during
10339  * this subtransaction as being the parent's responsibility.
10340  */
10341 void
10342 AtEOSubXact_on_commit_actions(bool isCommit, SubTransactionId mySubid,
10343                               SubTransactionId parentSubid)
10344 {
10345     ListCell   *cur_item;
10346     ListCell   *prev_item;
10347 
10348     prev_item = NULL;
10349     cur_item = list_head(on_commits);
10350 
10351     while (cur_item != NULL)
10352     {
10353         OnCommitItem *oc = (OnCommitItem *) lfirst(cur_item);
10354 
10355         if (!isCommit && oc->creating_subid == mySubid)
10356         {
10357             /* cur_item must be removed */
10358             on_commits = list_delete_cell(on_commits, cur_item, prev_item);
10359             pfree(oc);
10360             if (prev_item)
10361                 cur_item = lnext(prev_item);
10362             else
10363                 cur_item = list_head(on_commits);
10364         }
10365         else
10366         {
10367             /* cur_item must be preserved */
10368             if (oc->creating_subid == mySubid)
10369                 oc->creating_subid = parentSubid;
10370             if (oc->deleting_subid == mySubid)
10371                 oc->deleting_subid = isCommit ? parentSubid : InvalidSubTransactionId;
10372             prev_item = cur_item;
10373             cur_item = lnext(prev_item);
10374         }
10375     }
10376 }
10377 
10378 /*
10379  * This is intended as a callback for RangeVarGetRelidExtended().  It allows
10380  * the relation to be locked only if (1) it's a plain table, materialized
10381  * view, or TOAST table and (2) the current user is the owner (or the
10382  * superuser).  This meets the permission-checking needs of CLUSTER, REINDEX
10383  * TABLE, and REFRESH MATERIALIZED VIEW; we expose it here so that it can be
10384  * used by all.
10385  */
10386 void
10387 RangeVarCallbackOwnsTable(const RangeVar *relation,
10388                           Oid relId, Oid oldRelId, void *arg)
10389 {
10390     char        relkind;
10391 
10392     /* Nothing to do if the relation was not found. */
10393     if (!OidIsValid(relId))
10394         return;
10395 
10396     /*
10397      * If the relation does exist, check whether it's an index.  But note that
10398      * the relation might have been dropped between the time we did the name
10399      * lookup and now.  In that case, there's nothing to do.
10400      */
10401     relkind = get_rel_relkind(relId);
10402     if (!relkind)
10403         return;
10404     if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE &&
10405         relkind != RELKIND_MATVIEW)
10406         ereport(ERROR,
10407                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10408                  errmsg("\"%s\" is not a table or materialized view", relation->relname)));
10409 
10410     /* Check permissions */
10411     if (!pg_class_ownercheck(relId, GetUserId()))
10412         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, relation->relname);
10413 }
10414 
10415 /*
10416  * Common RangeVarGetRelid callback for rename, set schema, and alter table
10417  * processing.
10418  */
10419 static void
10420 RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, Oid oldrelid,
10421                                  void *arg)
10422 {
10423     Node       *stmt = (Node *) arg;
10424     ObjectType  reltype;
10425     HeapTuple   tuple;
10426     Form_pg_class classform;
10427     AclResult   aclresult;
10428     char        relkind;
10429 
10430     tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
10431     if (!HeapTupleIsValid(tuple))
10432         return;                 /* concurrently dropped */
10433     classform = (Form_pg_class) GETSTRUCT(tuple);
10434     relkind = classform->relkind;
10435 
10436     /* Must own relation. */
10437     if (!pg_class_ownercheck(relid, GetUserId()))
10438         aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, rv->relname);
10439 
10440     /* No system table modifications unless explicitly allowed. */
10441     if (!allowSystemTableMods && IsSystemClass(classform))
10442         ereport(ERROR,
10443                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
10444                  errmsg("permission denied: \"%s\" is a system catalog",
10445                         rv->relname)));
10446 
10447     /*
10448      * Extract the specified relation type from the statement parse tree.
10449      *
10450      * Also, for ALTER .. RENAME, check permissions: the user must (still)
10451      * have CREATE rights on the containing namespace.
10452      */
10453     if (IsA(stmt, RenameStmt))
10454     {
10455         aclresult = pg_namespace_aclcheck(classform->relnamespace,
10456                                           GetUserId(), ACL_CREATE);
10457         if (aclresult != ACLCHECK_OK)
10458             aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
10459                            get_namespace_name(classform->relnamespace));
10460         reltype = ((RenameStmt *) stmt)->renameType;
10461     }
10462     else if (IsA(stmt, AlterObjectSchemaStmt))
10463         reltype = ((AlterObjectSchemaStmt *) stmt)->objectType;
10464 
10465     else if (IsA(stmt, AlterTableStmt))
10466         reltype = ((AlterTableStmt *) stmt)->relkind;
10467     else
10468     {
10469         reltype = OBJECT_TABLE; /* placate compiler */
10470         elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
10471     }
10472 
10473     /*
10474      * For compatibility with prior releases, we allow ALTER TABLE to be used
10475      * with most other types of relations (but not composite types). We allow
10476      * similar flexibility for ALTER INDEX in the case of RENAME, but not
10477      * otherwise.  Otherwise, the user must select the correct form of the
10478      * command for the relation at issue.
10479      */
10480     if (reltype == OBJECT_SEQUENCE && relkind != RELKIND_SEQUENCE)
10481         ereport(ERROR,
10482                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10483                  errmsg("\"%s\" is not a sequence", rv->relname)));
10484 
10485     if (reltype == OBJECT_VIEW && relkind != RELKIND_VIEW)
10486         ereport(ERROR,
10487                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10488                  errmsg("\"%s\" is not a view", rv->relname)));
10489 
10490     if (reltype == OBJECT_MATVIEW && relkind != RELKIND_MATVIEW)
10491         ereport(ERROR,
10492                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10493                  errmsg("\"%s\" is not a materialized view", rv->relname)));
10494 
10495     if (reltype == OBJECT_FOREIGN_TABLE && relkind != RELKIND_FOREIGN_TABLE)
10496         ereport(ERROR,
10497                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10498                  errmsg("\"%s\" is not a foreign table", rv->relname)));
10499 
10500     if (reltype == OBJECT_TYPE && relkind != RELKIND_COMPOSITE_TYPE)
10501         ereport(ERROR,
10502                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10503                  errmsg("\"%s\" is not a composite type", rv->relname)));
10504 
10505     if (reltype == OBJECT_INDEX && relkind != RELKIND_INDEX
10506         && !IsA(stmt, RenameStmt))
10507         ereport(ERROR,
10508                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10509                  errmsg("\"%s\" is not an index", rv->relname)));
10510 
10511     /*
10512      * Don't allow ALTER TABLE on composite types. We want people to use ALTER
10513      * TYPE for that.
10514      */
10515     if (reltype != OBJECT_TYPE && relkind == RELKIND_COMPOSITE_TYPE)
10516         ereport(ERROR,
10517                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10518                  errmsg("\"%s\" is a composite type", rv->relname),
10519                  errhint("Use ALTER TYPE instead.")));
10520 
10521     if (reltype != OBJECT_FOREIGN_TABLE && relkind == RELKIND_FOREIGN_TABLE)
10522         ereport(ERROR,
10523                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10524                  errmsg("\"%s\" is a foreign table", rv->relname),
10525                  errhint("Use ALTER FOREIGN TABLE instead.")));
10526 
10527     /*
10528      * Don't allow ALTER TABLE .. SET SCHEMA on relations that can't be moved
10529      * to a different schema, such as indexes and TOAST tables.
10530      */
10531     if (IsA(stmt, AlterObjectSchemaStmt) && relkind != RELKIND_RELATION
10532         && relkind != RELKIND_VIEW && relkind != RELKIND_MATVIEW
10533         && relkind != RELKIND_SEQUENCE && relkind != RELKIND_FOREIGN_TABLE)
10534         ereport(ERROR,
10535                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
10536             errmsg("\"%s\" is not a table, view, sequence, or foreign table",
10537                    rv->relname)));
10538 
10539     ReleaseSysCache(tuple);
10540 }