Header And Logo

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

parse_utilcmd.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * parse_utilcmd.c
00004  *    Perform parse analysis work for various utility commands
00005  *
00006  * Formerly we did this work during parse_analyze() in analyze.c.  However
00007  * that is fairly unsafe in the presence of querytree caching, since any
00008  * database state that we depend on in making the transformations might be
00009  * obsolete by the time the utility command is executed; and utility commands
00010  * have no infrastructure for holding locks or rechecking plan validity.
00011  * Hence these functions are now called at the start of execution of their
00012  * respective utility commands.
00013  *
00014  * NOTE: in general we must avoid scribbling on the passed-in raw parse
00015  * tree, since it might be in a plan cache.  The simplest solution is
00016  * a quick copyObject() call before manipulating the query tree.
00017  *
00018  *
00019  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00020  * Portions Copyright (c) 1994, Regents of the University of California
00021  *
00022  *  src/backend/parser/parse_utilcmd.c
00023  *
00024  *-------------------------------------------------------------------------
00025  */
00026 
00027 #include "postgres.h"
00028 
00029 #include "access/htup_details.h"
00030 #include "access/reloptions.h"
00031 #include "catalog/dependency.h"
00032 #include "catalog/heap.h"
00033 #include "catalog/index.h"
00034 #include "catalog/namespace.h"
00035 #include "catalog/pg_collation.h"
00036 #include "catalog/pg_constraint.h"
00037 #include "catalog/pg_opclass.h"
00038 #include "catalog/pg_operator.h"
00039 #include "catalog/pg_type.h"
00040 #include "commands/comment.h"
00041 #include "commands/defrem.h"
00042 #include "commands/tablecmds.h"
00043 #include "commands/tablespace.h"
00044 #include "miscadmin.h"
00045 #include "nodes/makefuncs.h"
00046 #include "nodes/nodeFuncs.h"
00047 #include "parser/analyze.h"
00048 #include "parser/parse_clause.h"
00049 #include "parser/parse_collate.h"
00050 #include "parser/parse_expr.h"
00051 #include "parser/parse_relation.h"
00052 #include "parser/parse_target.h"
00053 #include "parser/parse_type.h"
00054 #include "parser/parse_utilcmd.h"
00055 #include "parser/parser.h"
00056 #include "rewrite/rewriteManip.h"
00057 #include "utils/acl.h"
00058 #include "utils/builtins.h"
00059 #include "utils/lsyscache.h"
00060 #include "utils/rel.h"
00061 #include "utils/syscache.h"
00062 #include "utils/typcache.h"
00063 
00064 
00065 /* State shared by transformCreateStmt and its subroutines */
00066 typedef struct
00067 {
00068     ParseState *pstate;         /* overall parser state */
00069     const char *stmtType;       /* "CREATE [FOREIGN] TABLE" or "ALTER TABLE" */
00070     RangeVar   *relation;       /* relation to create */
00071     Relation    rel;            /* opened/locked rel, if ALTER */
00072     List       *inhRelations;   /* relations to inherit from */
00073     bool        isforeign;      /* true if CREATE/ALTER FOREIGN TABLE */
00074     bool        isalter;        /* true if altering existing table */
00075     bool        hasoids;        /* does relation have an OID column? */
00076     List       *columns;        /* ColumnDef items */
00077     List       *ckconstraints;  /* CHECK constraints */
00078     List       *fkconstraints;  /* FOREIGN KEY constraints */
00079     List       *ixconstraints;  /* index-creating constraints */
00080     List       *inh_indexes;    /* cloned indexes from INCLUDING INDEXES */
00081     List       *blist;          /* "before list" of things to do before
00082                                  * creating the table */
00083     List       *alist;          /* "after list" of things to do after creating
00084                                  * the table */
00085     IndexStmt  *pkey;           /* PRIMARY KEY index, if any */
00086 } CreateStmtContext;
00087 
00088 /* State shared by transformCreateSchemaStmt and its subroutines */
00089 typedef struct
00090 {
00091     const char *stmtType;       /* "CREATE SCHEMA" or "ALTER SCHEMA" */
00092     char       *schemaname;     /* name of schema */
00093     char       *authid;         /* owner of schema */
00094     List       *sequences;      /* CREATE SEQUENCE items */
00095     List       *tables;         /* CREATE TABLE items */
00096     List       *views;          /* CREATE VIEW items */
00097     List       *indexes;        /* CREATE INDEX items */
00098     List       *triggers;       /* CREATE TRIGGER items */
00099     List       *grants;         /* GRANT items */
00100 } CreateSchemaStmtContext;
00101 
00102 
00103 static void transformColumnDefinition(CreateStmtContext *cxt,
00104                           ColumnDef *column);
00105 static void transformTableConstraint(CreateStmtContext *cxt,
00106                          Constraint *constraint);
00107 static void transformTableLikeClause(CreateStmtContext *cxt,
00108                          TableLikeClause *table_like_clause);
00109 static void transformOfType(CreateStmtContext *cxt,
00110                 TypeName *ofTypename);
00111 static IndexStmt *generateClonedIndexStmt(CreateStmtContext *cxt,
00112                         Relation source_idx,
00113                         const AttrNumber *attmap, int attmap_length);
00114 static List *get_collation(Oid collation, Oid actual_datatype);
00115 static List *get_opclass(Oid opclass, Oid actual_datatype);
00116 static void transformIndexConstraints(CreateStmtContext *cxt);
00117 static IndexStmt *transformIndexConstraint(Constraint *constraint,
00118                          CreateStmtContext *cxt);
00119 static void transformFKConstraints(CreateStmtContext *cxt,
00120                        bool skipValidation,
00121                        bool isAddConstraint);
00122 static void transformConstraintAttrs(CreateStmtContext *cxt,
00123                          List *constraintList);
00124 static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
00125 static void setSchemaName(char *context_schema, char **stmt_schema_name);
00126 
00127 
00128 /*
00129  * transformCreateStmt -
00130  *    parse analysis for CREATE TABLE
00131  *
00132  * Returns a List of utility commands to be done in sequence.  One of these
00133  * will be the transformed CreateStmt, but there may be additional actions
00134  * to be done before and after the actual DefineRelation() call.
00135  *
00136  * SQL allows constraints to be scattered all over, so thumb through
00137  * the columns and collect all constraints into one place.
00138  * If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
00139  * then expand those into multiple IndexStmt blocks.
00140  *    - thomas 1997-12-02
00141  */
00142 List *
00143 transformCreateStmt(CreateStmt *stmt, const char *queryString)
00144 {
00145     ParseState *pstate;
00146     CreateStmtContext cxt;
00147     List       *result;
00148     List       *save_alist;
00149     ListCell   *elements;
00150     Oid         namespaceid;
00151     Oid         existing_relid;
00152 
00153     /*
00154      * We must not scribble on the passed-in CreateStmt, so copy it.  (This is
00155      * overkill, but easy.)
00156      */
00157     stmt = (CreateStmt *) copyObject(stmt);
00158 
00159     /*
00160      * Look up the creation namespace.  This also checks permissions on the
00161      * target namespace, locks it against concurrent drops, checks for a
00162      * preexisting relation in that namespace with the same name, and updates
00163      * stmt->relation->relpersistence if the select namespace is temporary.
00164      */
00165     namespaceid =
00166         RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock,
00167                                              &existing_relid);
00168 
00169     /*
00170      * If the relation already exists and the user specified "IF NOT EXISTS",
00171      * bail out with a NOTICE.
00172      */
00173     if (stmt->if_not_exists && OidIsValid(existing_relid))
00174     {
00175         ereport(NOTICE,
00176                 (errcode(ERRCODE_DUPLICATE_TABLE),
00177                  errmsg("relation \"%s\" already exists, skipping",
00178                         stmt->relation->relname)));
00179         return NIL;
00180     }
00181 
00182     /*
00183      * If the target relation name isn't schema-qualified, make it so.  This
00184      * prevents some corner cases in which added-on rewritten commands might
00185      * think they should apply to other relations that have the same name and
00186      * are earlier in the search path.  But a local temp table is effectively
00187      * specified to be in pg_temp, so no need for anything extra in that case.
00188      */
00189     if (stmt->relation->schemaname == NULL
00190         && stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
00191         stmt->relation->schemaname = get_namespace_name(namespaceid);
00192 
00193     /* Set up pstate and CreateStmtContext */
00194     pstate = make_parsestate(NULL);
00195     pstate->p_sourcetext = queryString;
00196 
00197     cxt.pstate = pstate;
00198     if (IsA(stmt, CreateForeignTableStmt))
00199     {
00200         cxt.stmtType = "CREATE FOREIGN TABLE";
00201         cxt.isforeign = true;
00202     }
00203     else
00204     {
00205         cxt.stmtType = "CREATE TABLE";
00206         cxt.isforeign = false;
00207     }
00208     cxt.relation = stmt->relation;
00209     cxt.rel = NULL;
00210     cxt.inhRelations = stmt->inhRelations;
00211     cxt.isalter = false;
00212     cxt.columns = NIL;
00213     cxt.ckconstraints = NIL;
00214     cxt.fkconstraints = NIL;
00215     cxt.ixconstraints = NIL;
00216     cxt.inh_indexes = NIL;
00217     cxt.blist = NIL;
00218     cxt.alist = NIL;
00219     cxt.pkey = NULL;
00220     cxt.hasoids = interpretOidsOption(stmt->options, true);
00221 
00222     Assert(!stmt->ofTypename || !stmt->inhRelations);   /* grammar enforces */
00223 
00224     if (stmt->ofTypename)
00225         transformOfType(&cxt, stmt->ofTypename);
00226 
00227     /*
00228      * Run through each primary element in the table creation clause. Separate
00229      * column defs from constraints, and do preliminary analysis.
00230      */
00231     foreach(elements, stmt->tableElts)
00232     {
00233         Node       *element = lfirst(elements);
00234 
00235         switch (nodeTag(element))
00236         {
00237             case T_ColumnDef:
00238                 transformColumnDefinition(&cxt, (ColumnDef *) element);
00239                 break;
00240 
00241             case T_Constraint:
00242                 transformTableConstraint(&cxt, (Constraint *) element);
00243                 break;
00244 
00245             case T_TableLikeClause:
00246                 transformTableLikeClause(&cxt, (TableLikeClause *) element);
00247                 break;
00248 
00249             default:
00250                 elog(ERROR, "unrecognized node type: %d",
00251                      (int) nodeTag(element));
00252                 break;
00253         }
00254     }
00255 
00256     /*
00257      * transformIndexConstraints wants cxt.alist to contain only index
00258      * statements, so transfer anything we already have into save_alist.
00259      */
00260     save_alist = cxt.alist;
00261     cxt.alist = NIL;
00262 
00263     Assert(stmt->constraints == NIL);
00264 
00265     /*
00266      * Postprocess constraints that give rise to index definitions.
00267      */
00268     transformIndexConstraints(&cxt);
00269 
00270     /*
00271      * Postprocess foreign-key constraints.
00272      */
00273     transformFKConstraints(&cxt, true, false);
00274 
00275     /*
00276      * Output results.
00277      */
00278     stmt->tableElts = cxt.columns;
00279     stmt->constraints = cxt.ckconstraints;
00280 
00281     result = lappend(cxt.blist, stmt);
00282     result = list_concat(result, cxt.alist);
00283     result = list_concat(result, save_alist);
00284 
00285     return result;
00286 }
00287 
00288 /*
00289  * transformColumnDefinition -
00290  *      transform a single ColumnDef within CREATE TABLE
00291  *      Also used in ALTER TABLE ADD COLUMN
00292  */
00293 static void
00294 transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
00295 {
00296     bool        is_serial;
00297     bool        saw_nullable;
00298     bool        saw_default;
00299     Constraint *constraint;
00300     ListCell   *clist;
00301 
00302     cxt->columns = lappend(cxt->columns, column);
00303 
00304     /* Check for SERIAL pseudo-types */
00305     is_serial = false;
00306     if (column->typeName
00307         && list_length(column->typeName->names) == 1
00308         && !column->typeName->pct_type)
00309     {
00310         char       *typname = strVal(linitial(column->typeName->names));
00311 
00312         if (strcmp(typname, "smallserial") == 0 ||
00313             strcmp(typname, "serial2") == 0)
00314         {
00315             is_serial = true;
00316             column->typeName->names = NIL;
00317             column->typeName->typeOid = INT2OID;
00318         }
00319         else if (strcmp(typname, "serial") == 0 ||
00320                  strcmp(typname, "serial4") == 0)
00321         {
00322             is_serial = true;
00323             column->typeName->names = NIL;
00324             column->typeName->typeOid = INT4OID;
00325         }
00326         else if (strcmp(typname, "bigserial") == 0 ||
00327                  strcmp(typname, "serial8") == 0)
00328         {
00329             is_serial = true;
00330             column->typeName->names = NIL;
00331             column->typeName->typeOid = INT8OID;
00332         }
00333 
00334         /*
00335          * We have to reject "serial[]" explicitly, because once we've set
00336          * typeid, LookupTypeName won't notice arrayBounds.  We don't need any
00337          * special coding for serial(typmod) though.
00338          */
00339         if (is_serial && column->typeName->arrayBounds != NIL)
00340             ereport(ERROR,
00341                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00342                      errmsg("array of serial is not implemented"),
00343                      parser_errposition(cxt->pstate,
00344                                         column->typeName->location)));
00345     }
00346 
00347     /* Do necessary work on the column type declaration */
00348     if (column->typeName)
00349         transformColumnType(cxt, column);
00350 
00351     /* Special actions for SERIAL pseudo-types */
00352     if (is_serial)
00353     {
00354         Oid         snamespaceid;
00355         char       *snamespace;
00356         char       *sname;
00357         char       *qstring;
00358         A_Const    *snamenode;
00359         TypeCast   *castnode;
00360         FuncCall   *funccallnode;
00361         CreateSeqStmt *seqstmt;
00362         AlterSeqStmt *altseqstmt;
00363         List       *attnamelist;
00364 
00365         /*
00366          * Determine namespace and name to use for the sequence.
00367          *
00368          * Although we use ChooseRelationName, it's not guaranteed that the
00369          * selected sequence name won't conflict; given sufficiently long
00370          * field names, two different serial columns in the same table could
00371          * be assigned the same sequence name, and we'd not notice since we
00372          * aren't creating the sequence quite yet.  In practice this seems
00373          * quite unlikely to be a problem, especially since few people would
00374          * need two serial columns in one table.
00375          */
00376         if (cxt->rel)
00377             snamespaceid = RelationGetNamespace(cxt->rel);
00378         else
00379         {
00380             snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
00381             RangeVarAdjustRelationPersistence(cxt->relation, snamespaceid);
00382         }
00383         snamespace = get_namespace_name(snamespaceid);
00384         sname = ChooseRelationName(cxt->relation->relname,
00385                                    column->colname,
00386                                    "seq",
00387                                    snamespaceid);
00388 
00389         ereport(DEBUG1,
00390                 (errmsg("%s will create implicit sequence \"%s\" for serial column \"%s.%s\"",
00391                         cxt->stmtType, sname,
00392                         cxt->relation->relname, column->colname)));
00393 
00394         /*
00395          * Build a CREATE SEQUENCE command to create the sequence object, and
00396          * add it to the list of things to be done before this CREATE/ALTER
00397          * TABLE.
00398          */
00399         seqstmt = makeNode(CreateSeqStmt);
00400         seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
00401         seqstmt->options = NIL;
00402 
00403         /*
00404          * If this is ALTER ADD COLUMN, make sure the sequence will be owned
00405          * by the table's owner.  The current user might be someone else
00406          * (perhaps a superuser, or someone who's only a member of the owning
00407          * role), but the SEQUENCE OWNED BY mechanisms will bleat unless table
00408          * and sequence have exactly the same owning role.
00409          */
00410         if (cxt->rel)
00411             seqstmt->ownerId = cxt->rel->rd_rel->relowner;
00412         else
00413             seqstmt->ownerId = InvalidOid;
00414 
00415         cxt->blist = lappend(cxt->blist, seqstmt);
00416 
00417         /*
00418          * Build an ALTER SEQUENCE ... OWNED BY command to mark the sequence
00419          * as owned by this column, and add it to the list of things to be
00420          * done after this CREATE/ALTER TABLE.
00421          */
00422         altseqstmt = makeNode(AlterSeqStmt);
00423         altseqstmt->sequence = makeRangeVar(snamespace, sname, -1);
00424         attnamelist = list_make3(makeString(snamespace),
00425                                  makeString(cxt->relation->relname),
00426                                  makeString(column->colname));
00427         altseqstmt->options = list_make1(makeDefElem("owned_by",
00428                                                      (Node *) attnamelist));
00429 
00430         cxt->alist = lappend(cxt->alist, altseqstmt);
00431 
00432         /*
00433          * Create appropriate constraints for SERIAL.  We do this in full,
00434          * rather than shortcutting, so that we will detect any conflicting
00435          * constraints the user wrote (like a different DEFAULT).
00436          *
00437          * Create an expression tree representing the function call
00438          * nextval('sequencename').  We cannot reduce the raw tree to cooked
00439          * form until after the sequence is created, but there's no need to do
00440          * so.
00441          */
00442         qstring = quote_qualified_identifier(snamespace, sname);
00443         snamenode = makeNode(A_Const);
00444         snamenode->val.type = T_String;
00445         snamenode->val.val.str = qstring;
00446         snamenode->location = -1;
00447         castnode = makeNode(TypeCast);
00448         castnode->typeName = SystemTypeName("regclass");
00449         castnode->arg = (Node *) snamenode;
00450         castnode->location = -1;
00451         funccallnode = makeNode(FuncCall);
00452         funccallnode->funcname = SystemFuncName("nextval");
00453         funccallnode->args = list_make1(castnode);
00454         funccallnode->agg_order = NIL;
00455         funccallnode->agg_star = false;
00456         funccallnode->agg_distinct = false;
00457         funccallnode->func_variadic = false;
00458         funccallnode->over = NULL;
00459         funccallnode->location = -1;
00460 
00461         constraint = makeNode(Constraint);
00462         constraint->contype = CONSTR_DEFAULT;
00463         constraint->location = -1;
00464         constraint->raw_expr = (Node *) funccallnode;
00465         constraint->cooked_expr = NULL;
00466         column->constraints = lappend(column->constraints, constraint);
00467 
00468         constraint = makeNode(Constraint);
00469         constraint->contype = CONSTR_NOTNULL;
00470         constraint->location = -1;
00471         column->constraints = lappend(column->constraints, constraint);
00472     }
00473 
00474     /* Process column constraints, if any... */
00475     transformConstraintAttrs(cxt, column->constraints);
00476 
00477     saw_nullable = false;
00478     saw_default = false;
00479 
00480     foreach(clist, column->constraints)
00481     {
00482         constraint = lfirst(clist);
00483         Assert(IsA(constraint, Constraint));
00484 
00485         switch (constraint->contype)
00486         {
00487             case CONSTR_NULL:
00488                 if (saw_nullable && column->is_not_null)
00489                     ereport(ERROR,
00490                             (errcode(ERRCODE_SYNTAX_ERROR),
00491                              errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
00492                                     column->colname, cxt->relation->relname),
00493                              parser_errposition(cxt->pstate,
00494                                                 constraint->location)));
00495                 column->is_not_null = FALSE;
00496                 saw_nullable = true;
00497                 break;
00498 
00499             case CONSTR_NOTNULL:
00500                 if (saw_nullable && !column->is_not_null)
00501                     ereport(ERROR,
00502                             (errcode(ERRCODE_SYNTAX_ERROR),
00503                              errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
00504                                     column->colname, cxt->relation->relname),
00505                              parser_errposition(cxt->pstate,
00506                                                 constraint->location)));
00507                 column->is_not_null = TRUE;
00508                 saw_nullable = true;
00509                 break;
00510 
00511             case CONSTR_DEFAULT:
00512                 if (saw_default)
00513                     ereport(ERROR,
00514                             (errcode(ERRCODE_SYNTAX_ERROR),
00515                              errmsg("multiple default values specified for column \"%s\" of table \"%s\"",
00516                                     column->colname, cxt->relation->relname),
00517                              parser_errposition(cxt->pstate,
00518                                                 constraint->location)));
00519                 column->raw_default = constraint->raw_expr;
00520                 Assert(constraint->cooked_expr == NULL);
00521                 saw_default = true;
00522                 break;
00523 
00524             case CONSTR_CHECK:
00525                 if (cxt->isforeign)
00526                     ereport(ERROR,
00527                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00528                              errmsg("constraints are not supported on foreign tables"),
00529                              parser_errposition(cxt->pstate,
00530                                                 constraint->location)));
00531                 cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
00532                 break;
00533 
00534             case CONSTR_PRIMARY:
00535             case CONSTR_UNIQUE:
00536                 if (cxt->isforeign)
00537                     ereport(ERROR,
00538                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00539                              errmsg("constraints are not supported on foreign tables"),
00540                              parser_errposition(cxt->pstate,
00541                                                 constraint->location)));
00542                 if (constraint->keys == NIL)
00543                     constraint->keys = list_make1(makeString(column->colname));
00544                 cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
00545                 break;
00546 
00547             case CONSTR_EXCLUSION:
00548                 /* grammar does not allow EXCLUDE as a column constraint */
00549                 elog(ERROR, "column exclusion constraints are not supported");
00550                 break;
00551 
00552             case CONSTR_FOREIGN:
00553                 if (cxt->isforeign)
00554                     ereport(ERROR,
00555                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00556                              errmsg("constraints are not supported on foreign tables"),
00557                              parser_errposition(cxt->pstate,
00558                                                 constraint->location)));
00559                 /*
00560                  * Fill in the current attribute's name and throw it into the
00561                  * list of FK constraints to be processed later.
00562                  */
00563                 constraint->fk_attrs = list_make1(makeString(column->colname));
00564                 cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
00565                 break;
00566 
00567             case CONSTR_ATTR_DEFERRABLE:
00568             case CONSTR_ATTR_NOT_DEFERRABLE:
00569             case CONSTR_ATTR_DEFERRED:
00570             case CONSTR_ATTR_IMMEDIATE:
00571                 /* transformConstraintAttrs took care of these */
00572                 break;
00573 
00574             default:
00575                 elog(ERROR, "unrecognized constraint type: %d",
00576                      constraint->contype);
00577                 break;
00578         }
00579     }
00580 
00581     /*
00582      * If needed, generate ALTER FOREIGN TABLE ALTER COLUMN statement to add
00583      * per-column foreign data wrapper options to this column after creation.
00584      */
00585     if (column->fdwoptions != NIL)
00586     {
00587         AlterTableStmt *stmt;
00588         AlterTableCmd *cmd;
00589 
00590         cmd = makeNode(AlterTableCmd);
00591         cmd->subtype = AT_AlterColumnGenericOptions;
00592         cmd->name = column->colname;
00593         cmd->def = (Node *) column->fdwoptions;
00594         cmd->behavior = DROP_RESTRICT;
00595         cmd->missing_ok = false;
00596 
00597         stmt = makeNode(AlterTableStmt);
00598         stmt->relation = cxt->relation;
00599         stmt->cmds = NIL;
00600         stmt->relkind = OBJECT_FOREIGN_TABLE;
00601         stmt->cmds = lappend(stmt->cmds, cmd);
00602 
00603         cxt->alist = lappend(cxt->alist, stmt);
00604     }
00605 }
00606 
00607 /*
00608  * transformTableConstraint
00609  *      transform a Constraint node within CREATE TABLE or ALTER TABLE
00610  */
00611 static void
00612 transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
00613 {
00614     if (cxt->isforeign)
00615         ereport(ERROR,
00616                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00617                  errmsg("constraints are not supported on foreign tables"),
00618                  parser_errposition(cxt->pstate,
00619                                     constraint->location)));
00620 
00621     switch (constraint->contype)
00622     {
00623         case CONSTR_PRIMARY:
00624         case CONSTR_UNIQUE:
00625         case CONSTR_EXCLUSION:
00626             cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
00627             break;
00628 
00629         case CONSTR_CHECK:
00630             cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
00631             break;
00632 
00633         case CONSTR_FOREIGN:
00634             cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
00635             break;
00636 
00637         case CONSTR_NULL:
00638         case CONSTR_NOTNULL:
00639         case CONSTR_DEFAULT:
00640         case CONSTR_ATTR_DEFERRABLE:
00641         case CONSTR_ATTR_NOT_DEFERRABLE:
00642         case CONSTR_ATTR_DEFERRED:
00643         case CONSTR_ATTR_IMMEDIATE:
00644             elog(ERROR, "invalid context for constraint type %d",
00645                  constraint->contype);
00646             break;
00647 
00648         default:
00649             elog(ERROR, "unrecognized constraint type: %d",
00650                  constraint->contype);
00651             break;
00652     }
00653 }
00654 
00655 /*
00656  * transformTableLikeClause
00657  *
00658  * Change the LIKE <srctable> portion of a CREATE TABLE statement into
00659  * column definitions which recreate the user defined column portions of
00660  * <srctable>.
00661  */
00662 static void
00663 transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause)
00664 {
00665     AttrNumber  parent_attno;
00666     Relation    relation;
00667     TupleDesc   tupleDesc;
00668     TupleConstr *constr;
00669     AttrNumber *attmap;
00670     AclResult   aclresult;
00671     char       *comment;
00672     ParseCallbackState pcbstate;
00673 
00674     setup_parser_errposition_callback(&pcbstate, cxt->pstate,
00675                                       table_like_clause->relation->location);
00676 
00677     /* we could support LIKE in many cases, but worry about it another day */
00678     if (cxt->isforeign)
00679         ereport(ERROR,
00680                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00681                  errmsg("LIKE is not supported for foreign tables")));
00682 
00683     relation = relation_openrv(table_like_clause->relation, AccessShareLock);
00684 
00685     if (relation->rd_rel->relkind != RELKIND_RELATION &&
00686         relation->rd_rel->relkind != RELKIND_VIEW &&
00687         relation->rd_rel->relkind != RELKIND_MATVIEW &&
00688         relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
00689         relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
00690         ereport(ERROR,
00691                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00692                  errmsg("\"%s\" is not a table, view, composite type, or foreign table",
00693                         RelationGetRelationName(relation))));
00694 
00695     cancel_parser_errposition_callback(&pcbstate);
00696 
00697     /*
00698      * Check for privileges
00699      */
00700     if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
00701     {
00702         aclresult = pg_type_aclcheck(relation->rd_rel->reltype, GetUserId(),
00703                                      ACL_USAGE);
00704         if (aclresult != ACLCHECK_OK)
00705             aclcheck_error(aclresult, ACL_KIND_TYPE,
00706                            RelationGetRelationName(relation));
00707     }
00708     else
00709     {
00710         aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
00711                                       ACL_SELECT);
00712         if (aclresult != ACLCHECK_OK)
00713             aclcheck_error(aclresult, ACL_KIND_CLASS,
00714                            RelationGetRelationName(relation));
00715     }
00716 
00717     tupleDesc = RelationGetDescr(relation);
00718     constr = tupleDesc->constr;
00719 
00720     /*
00721      * Initialize column number map for map_variable_attnos().  We need this
00722      * since dropped columns in the source table aren't copied, so the new
00723      * table can have different column numbers.
00724      */
00725     attmap = (AttrNumber *) palloc0(sizeof(AttrNumber) * tupleDesc->natts);
00726 
00727     /*
00728      * Insert the copied attributes into the cxt for the new table definition.
00729      */
00730     for (parent_attno = 1; parent_attno <= tupleDesc->natts;
00731          parent_attno++)
00732     {
00733         Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
00734         char       *attributeName = NameStr(attribute->attname);
00735         ColumnDef  *def;
00736 
00737         /*
00738          * Ignore dropped columns in the parent.  attmap entry is left zero.
00739          */
00740         if (attribute->attisdropped)
00741             continue;
00742 
00743         /*
00744          * Create a new column, which is marked as NOT inherited.
00745          *
00746          * For constraints, ONLY the NOT NULL constraint is inherited by the
00747          * new column definition per SQL99.
00748          */
00749         def = makeNode(ColumnDef);
00750         def->colname = pstrdup(attributeName);
00751         def->typeName = makeTypeNameFromOid(attribute->atttypid,
00752                                             attribute->atttypmod);
00753         def->inhcount = 0;
00754         def->is_local = true;
00755         def->is_not_null = attribute->attnotnull;
00756         def->is_from_type = false;
00757         def->storage = 0;
00758         def->raw_default = NULL;
00759         def->cooked_default = NULL;
00760         def->collClause = NULL;
00761         def->collOid = attribute->attcollation;
00762         def->constraints = NIL;
00763 
00764         /*
00765          * Add to column list
00766          */
00767         cxt->columns = lappend(cxt->columns, def);
00768 
00769         attmap[parent_attno - 1] = list_length(cxt->columns);
00770 
00771         /*
00772          * Copy default, if present and the default has been requested
00773          */
00774         if (attribute->atthasdef &&
00775             (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS))
00776         {
00777             Node       *this_default = NULL;
00778             AttrDefault *attrdef;
00779             int         i;
00780 
00781             /* Find default in constraint structure */
00782             Assert(constr != NULL);
00783             attrdef = constr->defval;
00784             for (i = 0; i < constr->num_defval; i++)
00785             {
00786                 if (attrdef[i].adnum == parent_attno)
00787                 {
00788                     this_default = stringToNode(attrdef[i].adbin);
00789                     break;
00790                 }
00791             }
00792             Assert(this_default != NULL);
00793 
00794             /*
00795              * If default expr could contain any vars, we'd need to fix 'em,
00796              * but it can't; so default is ready to apply to child.
00797              */
00798 
00799             def->cooked_default = this_default;
00800         }
00801 
00802         /* Likewise, copy storage if requested */
00803         if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
00804             def->storage = attribute->attstorage;
00805         else
00806             def->storage = 0;
00807 
00808         /* Likewise, copy comment if requested */
00809         if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
00810             (comment = GetComment(attribute->attrelid,
00811                                   RelationRelationId,
00812                                   attribute->attnum)) != NULL)
00813         {
00814             CommentStmt *stmt = makeNode(CommentStmt);
00815 
00816             stmt->objtype = OBJECT_COLUMN;
00817             stmt->objname = list_make3(makeString(cxt->relation->schemaname),
00818                                        makeString(cxt->relation->relname),
00819                                        makeString(def->colname));
00820             stmt->objargs = NIL;
00821             stmt->comment = comment;
00822 
00823             cxt->alist = lappend(cxt->alist, stmt);
00824         }
00825     }
00826 
00827     /*
00828      * Copy CHECK constraints if requested, being careful to adjust attribute
00829      * numbers so they match the child.
00830      */
00831     if ((table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS) &&
00832         tupleDesc->constr)
00833     {
00834         int         ccnum;
00835 
00836         for (ccnum = 0; ccnum < tupleDesc->constr->num_check; ccnum++)
00837         {
00838             char       *ccname = tupleDesc->constr->check[ccnum].ccname;
00839             char       *ccbin = tupleDesc->constr->check[ccnum].ccbin;
00840             Constraint *n = makeNode(Constraint);
00841             Node       *ccbin_node;
00842             bool        found_whole_row;
00843 
00844             ccbin_node = map_variable_attnos(stringToNode(ccbin),
00845                                              1, 0,
00846                                              attmap, tupleDesc->natts,
00847                                              &found_whole_row);
00848 
00849             /*
00850              * We reject whole-row variables because the whole point of LIKE
00851              * is that the new table's rowtype might later diverge from the
00852              * parent's.  So, while translation might be possible right now,
00853              * it wouldn't be possible to guarantee it would work in future.
00854              */
00855             if (found_whole_row)
00856                 ereport(ERROR,
00857                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00858                          errmsg("cannot convert whole-row table reference"),
00859                          errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
00860                                    ccname,
00861                                    RelationGetRelationName(relation))));
00862 
00863             n->contype = CONSTR_CHECK;
00864             n->location = -1;
00865             n->conname = pstrdup(ccname);
00866             n->raw_expr = NULL;
00867             n->cooked_expr = nodeToString(ccbin_node);
00868             cxt->ckconstraints = lappend(cxt->ckconstraints, n);
00869 
00870             /* Copy comment on constraint */
00871             if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
00872                 (comment = GetComment(get_relation_constraint_oid(RelationGetRelid(relation),
00873                                                           n->conname, false),
00874                                       ConstraintRelationId,
00875                                       0)) != NULL)
00876             {
00877                 CommentStmt *stmt = makeNode(CommentStmt);
00878 
00879                 stmt->objtype = OBJECT_CONSTRAINT;
00880                 stmt->objname = list_make3(makeString(cxt->relation->schemaname),
00881                                            makeString(cxt->relation->relname),
00882                                            makeString(n->conname));
00883                 stmt->objargs = NIL;
00884                 stmt->comment = comment;
00885 
00886                 cxt->alist = lappend(cxt->alist, stmt);
00887             }
00888         }
00889     }
00890 
00891     /*
00892      * Likewise, copy indexes if requested
00893      */
00894     if ((table_like_clause->options & CREATE_TABLE_LIKE_INDEXES) &&
00895         relation->rd_rel->relhasindex)
00896     {
00897         List       *parent_indexes;
00898         ListCell   *l;
00899 
00900         parent_indexes = RelationGetIndexList(relation);
00901 
00902         foreach(l, parent_indexes)
00903         {
00904             Oid         parent_index_oid = lfirst_oid(l);
00905             Relation    parent_index;
00906             IndexStmt  *index_stmt;
00907 
00908             parent_index = index_open(parent_index_oid, AccessShareLock);
00909 
00910             /* Build CREATE INDEX statement to recreate the parent_index */
00911             index_stmt = generateClonedIndexStmt(cxt, parent_index,
00912                                                  attmap, tupleDesc->natts);
00913 
00914             /* Copy comment on index, if requested */
00915             if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
00916             {
00917                 comment = GetComment(parent_index_oid, RelationRelationId, 0);
00918 
00919                 /*
00920                  * We make use of IndexStmt's idxcomment option, so as not to
00921                  * need to know now what name the index will have.
00922                  */
00923                 index_stmt->idxcomment = comment;
00924             }
00925 
00926             /* Save it in the inh_indexes list for the time being */
00927             cxt->inh_indexes = lappend(cxt->inh_indexes, index_stmt);
00928 
00929             index_close(parent_index, AccessShareLock);
00930         }
00931     }
00932 
00933     /*
00934      * Close the parent rel, but keep our AccessShareLock on it until xact
00935      * commit.  That will prevent someone else from deleting or ALTERing the
00936      * parent before the child is committed.
00937      */
00938     heap_close(relation, NoLock);
00939 }
00940 
00941 static void
00942 transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
00943 {
00944     HeapTuple   tuple;
00945     TupleDesc   tupdesc;
00946     int         i;
00947     Oid         ofTypeId;
00948 
00949     AssertArg(ofTypename);
00950 
00951     tuple = typenameType(NULL, ofTypename, NULL);
00952     check_of_type(tuple);
00953     ofTypeId = HeapTupleGetOid(tuple);
00954     ofTypename->typeOid = ofTypeId;     /* cached for later */
00955 
00956     tupdesc = lookup_rowtype_tupdesc(ofTypeId, -1);
00957     for (i = 0; i < tupdesc->natts; i++)
00958     {
00959         Form_pg_attribute attr = tupdesc->attrs[i];
00960         ColumnDef  *n;
00961 
00962         if (attr->attisdropped)
00963             continue;
00964 
00965         n = makeNode(ColumnDef);
00966         n->colname = pstrdup(NameStr(attr->attname));
00967         n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod);
00968         n->inhcount = 0;
00969         n->is_local = true;
00970         n->is_not_null = false;
00971         n->is_from_type = true;
00972         n->storage = 0;
00973         n->raw_default = NULL;
00974         n->cooked_default = NULL;
00975         n->collClause = NULL;
00976         n->collOid = attr->attcollation;
00977         n->constraints = NIL;
00978         cxt->columns = lappend(cxt->columns, n);
00979     }
00980     DecrTupleDescRefCount(tupdesc);
00981 
00982     ReleaseSysCache(tuple);
00983 }
00984 
00985 /*
00986  * Generate an IndexStmt node using information from an already existing index
00987  * "source_idx".  Attribute numbers should be adjusted according to attmap.
00988  */
00989 static IndexStmt *
00990 generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
00991                         const AttrNumber *attmap, int attmap_length)
00992 {
00993     Oid         source_relid = RelationGetRelid(source_idx);
00994     Form_pg_attribute *attrs = RelationGetDescr(source_idx)->attrs;
00995     HeapTuple   ht_idxrel;
00996     HeapTuple   ht_idx;
00997     Form_pg_class idxrelrec;
00998     Form_pg_index idxrec;
00999     Form_pg_am  amrec;
01000     oidvector  *indcollation;
01001     oidvector  *indclass;
01002     IndexStmt  *index;
01003     List       *indexprs;
01004     ListCell   *indexpr_item;
01005     Oid         indrelid;
01006     int         keyno;
01007     Oid         keycoltype;
01008     Datum       datum;
01009     bool        isnull;
01010 
01011     /*
01012      * Fetch pg_class tuple of source index.  We can't use the copy in the
01013      * relcache entry because it doesn't include optional fields.
01014      */
01015     ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(source_relid));
01016     if (!HeapTupleIsValid(ht_idxrel))
01017         elog(ERROR, "cache lookup failed for relation %u", source_relid);
01018     idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
01019 
01020     /* Fetch pg_index tuple for source index from relcache entry */
01021     ht_idx = source_idx->rd_indextuple;
01022     idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
01023     indrelid = idxrec->indrelid;
01024 
01025     /* Fetch pg_am tuple for source index from relcache entry */
01026     amrec = source_idx->rd_am;
01027 
01028     /* Extract indcollation from the pg_index tuple */
01029     datum = SysCacheGetAttr(INDEXRELID, ht_idx,
01030                             Anum_pg_index_indcollation, &isnull);
01031     Assert(!isnull);
01032     indcollation = (oidvector *) DatumGetPointer(datum);
01033 
01034     /* Extract indclass from the pg_index tuple */
01035     datum = SysCacheGetAttr(INDEXRELID, ht_idx,
01036                             Anum_pg_index_indclass, &isnull);
01037     Assert(!isnull);
01038     indclass = (oidvector *) DatumGetPointer(datum);
01039 
01040     /* Begin building the IndexStmt */
01041     index = makeNode(IndexStmt);
01042     index->relation = cxt->relation;
01043     index->accessMethod = pstrdup(NameStr(amrec->amname));
01044     if (OidIsValid(idxrelrec->reltablespace))
01045         index->tableSpace = get_tablespace_name(idxrelrec->reltablespace);
01046     else
01047         index->tableSpace = NULL;
01048     index->excludeOpNames = NIL;
01049     index->idxcomment = NULL;
01050     index->indexOid = InvalidOid;
01051     index->oldNode = InvalidOid;
01052     index->unique = idxrec->indisunique;
01053     index->primary = idxrec->indisprimary;
01054     index->concurrent = false;
01055 
01056     /*
01057      * We don't try to preserve the name of the source index; instead, just
01058      * let DefineIndex() choose a reasonable name.
01059      */
01060     index->idxname = NULL;
01061 
01062     /*
01063      * If the index is marked PRIMARY or has an exclusion condition, it's
01064      * certainly from a constraint; else, if it's not marked UNIQUE, it
01065      * certainly isn't.  If it is or might be from a constraint, we have to
01066      * fetch the pg_constraint record.
01067      */
01068     if (index->primary || index->unique || idxrec->indisexclusion)
01069     {
01070         Oid         constraintId = get_index_constraint(source_relid);
01071 
01072         if (OidIsValid(constraintId))
01073         {
01074             HeapTuple   ht_constr;
01075             Form_pg_constraint conrec;
01076 
01077             ht_constr = SearchSysCache1(CONSTROID,
01078                                         ObjectIdGetDatum(constraintId));
01079             if (!HeapTupleIsValid(ht_constr))
01080                 elog(ERROR, "cache lookup failed for constraint %u",
01081                      constraintId);
01082             conrec = (Form_pg_constraint) GETSTRUCT(ht_constr);
01083 
01084             index->isconstraint = true;
01085             index->deferrable = conrec->condeferrable;
01086             index->initdeferred = conrec->condeferred;
01087 
01088             /* If it's an exclusion constraint, we need the operator names */
01089             if (idxrec->indisexclusion)
01090             {
01091                 Datum      *elems;
01092                 int         nElems;
01093                 int         i;
01094 
01095                 Assert(conrec->contype == CONSTRAINT_EXCLUSION);
01096                 /* Extract operator OIDs from the pg_constraint tuple */
01097                 datum = SysCacheGetAttr(CONSTROID, ht_constr,
01098                                         Anum_pg_constraint_conexclop,
01099                                         &isnull);
01100                 if (isnull)
01101                     elog(ERROR, "null conexclop for constraint %u",
01102                          constraintId);
01103 
01104                 deconstruct_array(DatumGetArrayTypeP(datum),
01105                                   OIDOID, sizeof(Oid), true, 'i',
01106                                   &elems, NULL, &nElems);
01107 
01108                 for (i = 0; i < nElems; i++)
01109                 {
01110                     Oid         operid = DatumGetObjectId(elems[i]);
01111                     HeapTuple   opertup;
01112                     Form_pg_operator operform;
01113                     char       *oprname;
01114                     char       *nspname;
01115                     List       *namelist;
01116 
01117                     opertup = SearchSysCache1(OPEROID,
01118                                               ObjectIdGetDatum(operid));
01119                     if (!HeapTupleIsValid(opertup))
01120                         elog(ERROR, "cache lookup failed for operator %u",
01121                              operid);
01122                     operform = (Form_pg_operator) GETSTRUCT(opertup);
01123                     oprname = pstrdup(NameStr(operform->oprname));
01124                     /* For simplicity we always schema-qualify the op name */
01125                     nspname = get_namespace_name(operform->oprnamespace);
01126                     namelist = list_make2(makeString(nspname),
01127                                           makeString(oprname));
01128                     index->excludeOpNames = lappend(index->excludeOpNames,
01129                                                     namelist);
01130                     ReleaseSysCache(opertup);
01131                 }
01132             }
01133 
01134             ReleaseSysCache(ht_constr);
01135         }
01136         else
01137             index->isconstraint = false;
01138     }
01139     else
01140         index->isconstraint = false;
01141 
01142     /* Get the index expressions, if any */
01143     datum = SysCacheGetAttr(INDEXRELID, ht_idx,
01144                             Anum_pg_index_indexprs, &isnull);
01145     if (!isnull)
01146     {
01147         char       *exprsString;
01148 
01149         exprsString = TextDatumGetCString(datum);
01150         indexprs = (List *) stringToNode(exprsString);
01151     }
01152     else
01153         indexprs = NIL;
01154 
01155     /* Build the list of IndexElem */
01156     index->indexParams = NIL;
01157 
01158     indexpr_item = list_head(indexprs);
01159     for (keyno = 0; keyno < idxrec->indnatts; keyno++)
01160     {
01161         IndexElem  *iparam;
01162         AttrNumber  attnum = idxrec->indkey.values[keyno];
01163         int16       opt = source_idx->rd_indoption[keyno];
01164 
01165         iparam = makeNode(IndexElem);
01166 
01167         if (AttributeNumberIsValid(attnum))
01168         {
01169             /* Simple index column */
01170             char       *attname;
01171 
01172             attname = get_relid_attribute_name(indrelid, attnum);
01173             keycoltype = get_atttype(indrelid, attnum);
01174 
01175             iparam->name = attname;
01176             iparam->expr = NULL;
01177         }
01178         else
01179         {
01180             /* Expressional index */
01181             Node       *indexkey;
01182             bool        found_whole_row;
01183 
01184             if (indexpr_item == NULL)
01185                 elog(ERROR, "too few entries in indexprs list");
01186             indexkey = (Node *) lfirst(indexpr_item);
01187             indexpr_item = lnext(indexpr_item);
01188 
01189             /* Adjust Vars to match new table's column numbering */
01190             indexkey = map_variable_attnos(indexkey,
01191                                            1, 0,
01192                                            attmap, attmap_length,
01193                                            &found_whole_row);
01194 
01195             /* As in transformTableLikeClause, reject whole-row variables */
01196             if (found_whole_row)
01197                 ereport(ERROR,
01198                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01199                          errmsg("cannot convert whole-row table reference"),
01200                          errdetail("Index \"%s\" contains a whole-row table reference.",
01201                                    RelationGetRelationName(source_idx))));
01202 
01203             iparam->name = NULL;
01204             iparam->expr = indexkey;
01205 
01206             keycoltype = exprType(indexkey);
01207         }
01208 
01209         /* Copy the original index column name */
01210         iparam->indexcolname = pstrdup(NameStr(attrs[keyno]->attname));
01211 
01212         /* Add the collation name, if non-default */
01213         iparam->collation = get_collation(indcollation->values[keyno], keycoltype);
01214 
01215         /* Add the operator class name, if non-default */
01216         iparam->opclass = get_opclass(indclass->values[keyno], keycoltype);
01217 
01218         iparam->ordering = SORTBY_DEFAULT;
01219         iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
01220 
01221         /* Adjust options if necessary */
01222         if (amrec->amcanorder)
01223         {
01224             /*
01225              * If it supports sort ordering, copy DESC and NULLS opts. Don't
01226              * set non-default settings unnecessarily, though, so as to
01227              * improve the chance of recognizing equivalence to constraint
01228              * indexes.
01229              */
01230             if (opt & INDOPTION_DESC)
01231             {
01232                 iparam->ordering = SORTBY_DESC;
01233                 if ((opt & INDOPTION_NULLS_FIRST) == 0)
01234                     iparam->nulls_ordering = SORTBY_NULLS_LAST;
01235             }
01236             else
01237             {
01238                 if (opt & INDOPTION_NULLS_FIRST)
01239                     iparam->nulls_ordering = SORTBY_NULLS_FIRST;
01240             }
01241         }
01242 
01243         index->indexParams = lappend(index->indexParams, iparam);
01244     }
01245 
01246     /* Copy reloptions if any */
01247     datum = SysCacheGetAttr(RELOID, ht_idxrel,
01248                             Anum_pg_class_reloptions, &isnull);
01249     if (!isnull)
01250         index->options = untransformRelOptions(datum);
01251 
01252     /* If it's a partial index, decompile and append the predicate */
01253     datum = SysCacheGetAttr(INDEXRELID, ht_idx,
01254                             Anum_pg_index_indpred, &isnull);
01255     if (!isnull)
01256     {
01257         char       *pred_str;
01258         Node       *pred_tree;
01259         bool        found_whole_row;
01260 
01261         /* Convert text string to node tree */
01262         pred_str = TextDatumGetCString(datum);
01263         pred_tree = (Node *) stringToNode(pred_str);
01264 
01265         /* Adjust Vars to match new table's column numbering */
01266         pred_tree = map_variable_attnos(pred_tree,
01267                                         1, 0,
01268                                         attmap, attmap_length,
01269                                         &found_whole_row);
01270 
01271         /* As in transformTableLikeClause, reject whole-row variables */
01272         if (found_whole_row)
01273             ereport(ERROR,
01274                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01275                      errmsg("cannot convert whole-row table reference"),
01276                      errdetail("Index \"%s\" contains a whole-row table reference.",
01277                                RelationGetRelationName(source_idx))));
01278 
01279         index->whereClause = pred_tree;
01280     }
01281 
01282     /* Clean up */
01283     ReleaseSysCache(ht_idxrel);
01284 
01285     return index;
01286 }
01287 
01288 /*
01289  * get_collation        - fetch qualified name of a collation
01290  *
01291  * If collation is InvalidOid or is the default for the given actual_datatype,
01292  * then the return value is NIL.
01293  */
01294 static List *
01295 get_collation(Oid collation, Oid actual_datatype)
01296 {
01297     List       *result;
01298     HeapTuple   ht_coll;
01299     Form_pg_collation coll_rec;
01300     char       *nsp_name;
01301     char       *coll_name;
01302 
01303     if (!OidIsValid(collation))
01304         return NIL;             /* easy case */
01305     if (collation == get_typcollation(actual_datatype))
01306         return NIL;             /* just let it default */
01307 
01308     ht_coll = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
01309     if (!HeapTupleIsValid(ht_coll))
01310         elog(ERROR, "cache lookup failed for collation %u", collation);
01311     coll_rec = (Form_pg_collation) GETSTRUCT(ht_coll);
01312 
01313     /* For simplicity, we always schema-qualify the name */
01314     nsp_name = get_namespace_name(coll_rec->collnamespace);
01315     coll_name = pstrdup(NameStr(coll_rec->collname));
01316     result = list_make2(makeString(nsp_name), makeString(coll_name));
01317 
01318     ReleaseSysCache(ht_coll);
01319     return result;
01320 }
01321 
01322 /*
01323  * get_opclass          - fetch qualified name of an index operator class
01324  *
01325  * If the opclass is the default for the given actual_datatype, then
01326  * the return value is NIL.
01327  */
01328 static List *
01329 get_opclass(Oid opclass, Oid actual_datatype)
01330 {
01331     List       *result = NIL;
01332     HeapTuple   ht_opc;
01333     Form_pg_opclass opc_rec;
01334 
01335     ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
01336     if (!HeapTupleIsValid(ht_opc))
01337         elog(ERROR, "cache lookup failed for opclass %u", opclass);
01338     opc_rec = (Form_pg_opclass) GETSTRUCT(ht_opc);
01339 
01340     if (GetDefaultOpClass(actual_datatype, opc_rec->opcmethod) != opclass)
01341     {
01342         /* For simplicity, we always schema-qualify the name */
01343         char       *nsp_name = get_namespace_name(opc_rec->opcnamespace);
01344         char       *opc_name = pstrdup(NameStr(opc_rec->opcname));
01345 
01346         result = list_make2(makeString(nsp_name), makeString(opc_name));
01347     }
01348 
01349     ReleaseSysCache(ht_opc);
01350     return result;
01351 }
01352 
01353 
01354 /*
01355  * transformIndexConstraints
01356  *      Handle UNIQUE, PRIMARY KEY, EXCLUDE constraints, which create indexes.
01357  *      We also merge in any index definitions arising from
01358  *      LIKE ... INCLUDING INDEXES.
01359  */
01360 static void
01361 transformIndexConstraints(CreateStmtContext *cxt)
01362 {
01363     IndexStmt  *index;
01364     List       *indexlist = NIL;
01365     ListCell   *lc;
01366 
01367     /*
01368      * Run through the constraints that need to generate an index. For PRIMARY
01369      * KEY, mark each column as NOT NULL and create an index. For UNIQUE or
01370      * EXCLUDE, create an index as for PRIMARY KEY, but do not insist on NOT
01371      * NULL.
01372      */
01373     foreach(lc, cxt->ixconstraints)
01374     {
01375         Constraint *constraint = (Constraint *) lfirst(lc);
01376 
01377         Assert(IsA(constraint, Constraint));
01378         Assert(constraint->contype == CONSTR_PRIMARY ||
01379                constraint->contype == CONSTR_UNIQUE ||
01380                constraint->contype == CONSTR_EXCLUSION);
01381 
01382         index = transformIndexConstraint(constraint, cxt);
01383 
01384         indexlist = lappend(indexlist, index);
01385     }
01386 
01387     /* Add in any indexes defined by LIKE ... INCLUDING INDEXES */
01388     foreach(lc, cxt->inh_indexes)
01389     {
01390         index = (IndexStmt *) lfirst(lc);
01391 
01392         if (index->primary)
01393         {
01394             if (cxt->pkey != NULL)
01395                 ereport(ERROR,
01396                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
01397                          errmsg("multiple primary keys for table \"%s\" are not allowed",
01398                                 cxt->relation->relname)));
01399             cxt->pkey = index;
01400         }
01401 
01402         indexlist = lappend(indexlist, index);
01403     }
01404 
01405     /*
01406      * Scan the index list and remove any redundant index specifications. This
01407      * can happen if, for instance, the user writes UNIQUE PRIMARY KEY. A
01408      * strict reading of SQL would suggest raising an error instead, but
01409      * that strikes me as too anal-retentive. - tgl 2001-02-14
01410      *
01411      * XXX in ALTER TABLE case, it'd be nice to look for duplicate
01412      * pre-existing indexes, too.
01413      */
01414     Assert(cxt->alist == NIL);
01415     if (cxt->pkey != NULL)
01416     {
01417         /* Make sure we keep the PKEY index in preference to others... */
01418         cxt->alist = list_make1(cxt->pkey);
01419     }
01420 
01421     foreach(lc, indexlist)
01422     {
01423         bool        keep = true;
01424         ListCell   *k;
01425 
01426         index = lfirst(lc);
01427 
01428         /* if it's pkey, it's already in cxt->alist */
01429         if (index == cxt->pkey)
01430             continue;
01431 
01432         foreach(k, cxt->alist)
01433         {
01434             IndexStmt  *priorindex = lfirst(k);
01435 
01436             if (equal(index->indexParams, priorindex->indexParams) &&
01437                 equal(index->whereClause, priorindex->whereClause) &&
01438                 equal(index->excludeOpNames, priorindex->excludeOpNames) &&
01439                 strcmp(index->accessMethod, priorindex->accessMethod) == 0 &&
01440                 index->deferrable == priorindex->deferrable &&
01441                 index->initdeferred == priorindex->initdeferred)
01442             {
01443                 priorindex->unique |= index->unique;
01444 
01445                 /*
01446                  * If the prior index is as yet unnamed, and this one is
01447                  * named, then transfer the name to the prior index. This
01448                  * ensures that if we have named and unnamed constraints,
01449                  * we'll use (at least one of) the names for the index.
01450                  */
01451                 if (priorindex->idxname == NULL)
01452                     priorindex->idxname = index->idxname;
01453                 keep = false;
01454                 break;
01455             }
01456         }
01457 
01458         if (keep)
01459             cxt->alist = lappend(cxt->alist, index);
01460     }
01461 }
01462 
01463 /*
01464  * transformIndexConstraint
01465  *      Transform one UNIQUE, PRIMARY KEY, or EXCLUDE constraint for
01466  *      transformIndexConstraints.
01467  */
01468 static IndexStmt *
01469 transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
01470 {
01471     IndexStmt  *index;
01472     ListCell   *lc;
01473 
01474     index = makeNode(IndexStmt);
01475 
01476     index->unique = (constraint->contype != CONSTR_EXCLUSION);
01477     index->primary = (constraint->contype == CONSTR_PRIMARY);
01478     if (index->primary)
01479     {
01480         if (cxt->pkey != NULL)
01481             ereport(ERROR,
01482                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
01483              errmsg("multiple primary keys for table \"%s\" are not allowed",
01484                     cxt->relation->relname),
01485                      parser_errposition(cxt->pstate, constraint->location)));
01486         cxt->pkey = index;
01487 
01488         /*
01489          * In ALTER TABLE case, a primary index might already exist, but
01490          * DefineIndex will check for it.
01491          */
01492     }
01493     index->isconstraint = true;
01494     index->deferrable = constraint->deferrable;
01495     index->initdeferred = constraint->initdeferred;
01496 
01497     if (constraint->conname != NULL)
01498         index->idxname = pstrdup(constraint->conname);
01499     else
01500         index->idxname = NULL;  /* DefineIndex will choose name */
01501 
01502     index->relation = cxt->relation;
01503     index->accessMethod = constraint->access_method ? constraint->access_method : DEFAULT_INDEX_TYPE;
01504     index->options = constraint->options;
01505     index->tableSpace = constraint->indexspace;
01506     index->whereClause = constraint->where_clause;
01507     index->indexParams = NIL;
01508     index->excludeOpNames = NIL;
01509     index->idxcomment = NULL;
01510     index->indexOid = InvalidOid;
01511     index->oldNode = InvalidOid;
01512     index->concurrent = false;
01513 
01514     /*
01515      * If it's ALTER TABLE ADD CONSTRAINT USING INDEX, look up the index and
01516      * verify it's usable, then extract the implied column name list.  (We
01517      * will not actually need the column name list at runtime, but we need it
01518      * now to check for duplicate column entries below.)
01519      */
01520     if (constraint->indexname != NULL)
01521     {
01522         char       *index_name = constraint->indexname;
01523         Relation    heap_rel = cxt->rel;
01524         Oid         index_oid;
01525         Relation    index_rel;
01526         Form_pg_index index_form;
01527         oidvector  *indclass;
01528         Datum       indclassDatum;
01529         bool        isnull;
01530         int         i;
01531 
01532         /* Grammar should not allow this with explicit column list */
01533         Assert(constraint->keys == NIL);
01534 
01535         /* Grammar should only allow PRIMARY and UNIQUE constraints */
01536         Assert(constraint->contype == CONSTR_PRIMARY ||
01537                constraint->contype == CONSTR_UNIQUE);
01538 
01539         /* Must be ALTER, not CREATE, but grammar doesn't enforce that */
01540         if (!cxt->isalter)
01541             ereport(ERROR,
01542                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01543                      errmsg("cannot use an existing index in CREATE TABLE"),
01544                      parser_errposition(cxt->pstate, constraint->location)));
01545 
01546         /* Look for the index in the same schema as the table */
01547         index_oid = get_relname_relid(index_name, RelationGetNamespace(heap_rel));
01548 
01549         if (!OidIsValid(index_oid))
01550             ereport(ERROR,
01551                     (errcode(ERRCODE_UNDEFINED_OBJECT),
01552                      errmsg("index \"%s\" does not exist", index_name),
01553                      parser_errposition(cxt->pstate, constraint->location)));
01554 
01555         /* Open the index (this will throw an error if it is not an index) */
01556         index_rel = index_open(index_oid, AccessShareLock);
01557         index_form = index_rel->rd_index;
01558 
01559         /* Check that it does not have an associated constraint already */
01560         if (OidIsValid(get_index_constraint(index_oid)))
01561             ereport(ERROR,
01562                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
01563                errmsg("index \"%s\" is already associated with a constraint",
01564                       index_name),
01565                      parser_errposition(cxt->pstate, constraint->location)));
01566 
01567         /* Perform validity checks on the index */
01568         if (index_form->indrelid != RelationGetRelid(heap_rel))
01569             ereport(ERROR,
01570                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
01571                      errmsg("index \"%s\" does not belong to table \"%s\"",
01572                             index_name, RelationGetRelationName(heap_rel)),
01573                      parser_errposition(cxt->pstate, constraint->location)));
01574 
01575         if (!IndexIsValid(index_form))
01576             ereport(ERROR,
01577                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
01578                      errmsg("index \"%s\" is not valid", index_name),
01579                      parser_errposition(cxt->pstate, constraint->location)));
01580 
01581         if (!index_form->indisunique)
01582             ereport(ERROR,
01583                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01584                      errmsg("\"%s\" is not a unique index", index_name),
01585                      errdetail("Cannot create a primary key or unique constraint using such an index."),
01586                      parser_errposition(cxt->pstate, constraint->location)));
01587 
01588         if (RelationGetIndexExpressions(index_rel) != NIL)
01589             ereport(ERROR,
01590                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01591                      errmsg("index \"%s\" contains expressions", index_name),
01592                      errdetail("Cannot create a primary key or unique constraint using such an index."),
01593                      parser_errposition(cxt->pstate, constraint->location)));
01594 
01595         if (RelationGetIndexPredicate(index_rel) != NIL)
01596             ereport(ERROR,
01597                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01598                      errmsg("\"%s\" is a partial index", index_name),
01599                      errdetail("Cannot create a primary key or unique constraint using such an index."),
01600                      parser_errposition(cxt->pstate, constraint->location)));
01601 
01602         /*
01603          * It's probably unsafe to change a deferred index to non-deferred. (A
01604          * non-constraint index couldn't be deferred anyway, so this case
01605          * should never occur; no need to sweat, but let's check it.)
01606          */
01607         if (!index_form->indimmediate && !constraint->deferrable)
01608             ereport(ERROR,
01609                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01610                      errmsg("\"%s\" is a deferrable index", index_name),
01611                      errdetail("Cannot create a non-deferrable constraint using a deferrable index."),
01612                      parser_errposition(cxt->pstate, constraint->location)));
01613 
01614         /*
01615          * Insist on it being a btree.  That's the only kind that supports
01616          * uniqueness at the moment anyway; but we must have an index that
01617          * exactly matches what you'd get from plain ADD CONSTRAINT syntax,
01618          * else dump and reload will produce a different index (breaking
01619          * pg_upgrade in particular).
01620          */
01621         if (index_rel->rd_rel->relam != get_am_oid(DEFAULT_INDEX_TYPE, false))
01622             ereport(ERROR,
01623                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01624                      errmsg("index \"%s\" is not a btree", index_name),
01625                      parser_errposition(cxt->pstate, constraint->location)));
01626 
01627         /* Must get indclass the hard way */
01628         indclassDatum = SysCacheGetAttr(INDEXRELID, index_rel->rd_indextuple,
01629                                         Anum_pg_index_indclass, &isnull);
01630         Assert(!isnull);
01631         indclass = (oidvector *) DatumGetPointer(indclassDatum);
01632 
01633         for (i = 0; i < index_form->indnatts; i++)
01634         {
01635             int16       attnum = index_form->indkey.values[i];
01636             Form_pg_attribute attform;
01637             char       *attname;
01638             Oid         defopclass;
01639 
01640             /*
01641              * We shouldn't see attnum == 0 here, since we already rejected
01642              * expression indexes.  If we do, SystemAttributeDefinition will
01643              * throw an error.
01644              */
01645             if (attnum > 0)
01646             {
01647                 Assert(attnum <= heap_rel->rd_att->natts);
01648                 attform = heap_rel->rd_att->attrs[attnum - 1];
01649             }
01650             else
01651                 attform = SystemAttributeDefinition(attnum,
01652                                                heap_rel->rd_rel->relhasoids);
01653             attname = pstrdup(NameStr(attform->attname));
01654 
01655             /*
01656              * Insist on default opclass and sort options.  While the index
01657              * would still work as a constraint with non-default settings, it
01658              * might not provide exactly the same uniqueness semantics as
01659              * you'd get from a normally-created constraint; and there's also
01660              * the dump/reload problem mentioned above.
01661              */
01662             defopclass = GetDefaultOpClass(attform->atttypid,
01663                                            index_rel->rd_rel->relam);
01664             if (indclass->values[i] != defopclass ||
01665                 index_rel->rd_indoption[i] != 0)
01666                 ereport(ERROR,
01667                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01668                          errmsg("index \"%s\" does not have default sorting behavior", index_name),
01669                          errdetail("Cannot create a primary key or unique constraint using such an index."),
01670                      parser_errposition(cxt->pstate, constraint->location)));
01671 
01672             constraint->keys = lappend(constraint->keys, makeString(attname));
01673         }
01674 
01675         /* Close the index relation but keep the lock */
01676         relation_close(index_rel, NoLock);
01677 
01678         index->indexOid = index_oid;
01679     }
01680 
01681     /*
01682      * If it's an EXCLUDE constraint, the grammar returns a list of pairs of
01683      * IndexElems and operator names.  We have to break that apart into
01684      * separate lists.
01685      */
01686     if (constraint->contype == CONSTR_EXCLUSION)
01687     {
01688         foreach(lc, constraint->exclusions)
01689         {
01690             List       *pair = (List *) lfirst(lc);
01691             IndexElem  *elem;
01692             List       *opname;
01693 
01694             Assert(list_length(pair) == 2);
01695             elem = (IndexElem *) linitial(pair);
01696             Assert(IsA(elem, IndexElem));
01697             opname = (List *) lsecond(pair);
01698             Assert(IsA(opname, List));
01699 
01700             index->indexParams = lappend(index->indexParams, elem);
01701             index->excludeOpNames = lappend(index->excludeOpNames, opname);
01702         }
01703 
01704         return index;
01705     }
01706 
01707     /*
01708      * For UNIQUE and PRIMARY KEY, we just have a list of column names.
01709      *
01710      * Make sure referenced keys exist.  If we are making a PRIMARY KEY index,
01711      * also make sure they are NOT NULL, if possible. (Although we could leave
01712      * it to DefineIndex to mark the columns NOT NULL, it's more efficient to
01713      * get it right the first time.)
01714      */
01715     foreach(lc, constraint->keys)
01716     {
01717         char       *key = strVal(lfirst(lc));
01718         bool        found = false;
01719         ColumnDef  *column = NULL;
01720         ListCell   *columns;
01721         IndexElem  *iparam;
01722 
01723         foreach(columns, cxt->columns)
01724         {
01725             column = (ColumnDef *) lfirst(columns);
01726             Assert(IsA(column, ColumnDef));
01727             if (strcmp(column->colname, key) == 0)
01728             {
01729                 found = true;
01730                 break;
01731             }
01732         }
01733         if (found)
01734         {
01735             /* found column in the new table; force it to be NOT NULL */
01736             if (constraint->contype == CONSTR_PRIMARY)
01737                 column->is_not_null = TRUE;
01738         }
01739         else if (SystemAttributeByName(key, cxt->hasoids) != NULL)
01740         {
01741             /*
01742              * column will be a system column in the new table, so accept it.
01743              * System columns can't ever be null, so no need to worry about
01744              * PRIMARY/NOT NULL constraint.
01745              */
01746             found = true;
01747         }
01748         else if (cxt->inhRelations)
01749         {
01750             /* try inherited tables */
01751             ListCell   *inher;
01752 
01753             foreach(inher, cxt->inhRelations)
01754             {
01755                 RangeVar   *inh = (RangeVar *) lfirst(inher);
01756                 Relation    rel;
01757                 int         count;
01758 
01759                 Assert(IsA(inh, RangeVar));
01760                 rel = heap_openrv(inh, AccessShareLock);
01761                 if (rel->rd_rel->relkind != RELKIND_RELATION)
01762                     ereport(ERROR,
01763                             (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01764                            errmsg("inherited relation \"%s\" is not a table",
01765                                   inh->relname)));
01766                 for (count = 0; count < rel->rd_att->natts; count++)
01767                 {
01768                     Form_pg_attribute inhattr = rel->rd_att->attrs[count];
01769                     char       *inhname = NameStr(inhattr->attname);
01770 
01771                     if (inhattr->attisdropped)
01772                         continue;
01773                     if (strcmp(key, inhname) == 0)
01774                     {
01775                         found = true;
01776 
01777                         /*
01778                          * We currently have no easy way to force an inherited
01779                          * column to be NOT NULL at creation, if its parent
01780                          * wasn't so already. We leave it to DefineIndex to
01781                          * fix things up in this case.
01782                          */
01783                         break;
01784                     }
01785                 }
01786                 heap_close(rel, NoLock);
01787                 if (found)
01788                     break;
01789             }
01790         }
01791 
01792         /*
01793          * In the ALTER TABLE case, don't complain about index keys not
01794          * created in the command; they may well exist already. DefineIndex
01795          * will complain about them if not, and will also take care of marking
01796          * them NOT NULL.
01797          */
01798         if (!found && !cxt->isalter)
01799             ereport(ERROR,
01800                     (errcode(ERRCODE_UNDEFINED_COLUMN),
01801                      errmsg("column \"%s\" named in key does not exist", key),
01802                      parser_errposition(cxt->pstate, constraint->location)));
01803 
01804         /* Check for PRIMARY KEY(foo, foo) */
01805         foreach(columns, index->indexParams)
01806         {
01807             iparam = (IndexElem *) lfirst(columns);
01808             if (iparam->name && strcmp(key, iparam->name) == 0)
01809             {
01810                 if (index->primary)
01811                     ereport(ERROR,
01812                             (errcode(ERRCODE_DUPLICATE_COLUMN),
01813                              errmsg("column \"%s\" appears twice in primary key constraint",
01814                                     key),
01815                      parser_errposition(cxt->pstate, constraint->location)));
01816                 else
01817                     ereport(ERROR,
01818                             (errcode(ERRCODE_DUPLICATE_COLUMN),
01819                     errmsg("column \"%s\" appears twice in unique constraint",
01820                            key),
01821                      parser_errposition(cxt->pstate, constraint->location)));
01822             }
01823         }
01824 
01825         /* OK, add it to the index definition */
01826         iparam = makeNode(IndexElem);
01827         iparam->name = pstrdup(key);
01828         iparam->expr = NULL;
01829         iparam->indexcolname = NULL;
01830         iparam->collation = NIL;
01831         iparam->opclass = NIL;
01832         iparam->ordering = SORTBY_DEFAULT;
01833         iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
01834         index->indexParams = lappend(index->indexParams, iparam);
01835     }
01836 
01837     return index;
01838 }
01839 
01840 /*
01841  * transformFKConstraints
01842  *      handle FOREIGN KEY constraints
01843  */
01844 static void
01845 transformFKConstraints(CreateStmtContext *cxt,
01846                        bool skipValidation, bool isAddConstraint)
01847 {
01848     ListCell   *fkclist;
01849 
01850     if (cxt->fkconstraints == NIL)
01851         return;
01852 
01853     /*
01854      * If CREATE TABLE or adding a column with NULL default, we can safely
01855      * skip validation of FK constraints, and nonetheless mark them valid.
01856      * (This will override any user-supplied NOT VALID flag.)
01857      */
01858     if (skipValidation)
01859     {
01860         foreach(fkclist, cxt->fkconstraints)
01861         {
01862             Constraint *constraint = (Constraint *) lfirst(fkclist);
01863 
01864             constraint->skip_validation = true;
01865             constraint->initially_valid = true;
01866         }
01867     }
01868 
01869     /*
01870      * For CREATE TABLE or ALTER TABLE ADD COLUMN, gin up an ALTER TABLE ADD
01871      * CONSTRAINT command to execute after the basic command is complete. (If
01872      * called from ADD CONSTRAINT, that routine will add the FK constraints to
01873      * its own subcommand list.)
01874      *
01875      * Note: the ADD CONSTRAINT command must also execute after any index
01876      * creation commands.  Thus, this should run after
01877      * transformIndexConstraints, so that the CREATE INDEX commands are
01878      * already in cxt->alist.
01879      */
01880     if (!isAddConstraint)
01881     {
01882         AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
01883 
01884         alterstmt->relation = cxt->relation;
01885         alterstmt->cmds = NIL;
01886         alterstmt->relkind = OBJECT_TABLE;
01887 
01888         foreach(fkclist, cxt->fkconstraints)
01889         {
01890             Constraint *constraint = (Constraint *) lfirst(fkclist);
01891             AlterTableCmd *altercmd = makeNode(AlterTableCmd);
01892 
01893             altercmd->subtype = AT_ProcessedConstraint;
01894             altercmd->name = NULL;
01895             altercmd->def = (Node *) constraint;
01896             alterstmt->cmds = lappend(alterstmt->cmds, altercmd);
01897         }
01898 
01899         cxt->alist = lappend(cxt->alist, alterstmt);
01900     }
01901 }
01902 
01903 /*
01904  * transformIndexStmt - parse analysis for CREATE INDEX and ALTER TABLE
01905  *
01906  * Note: this is a no-op for an index not using either index expressions or
01907  * a predicate expression.  There are several code paths that create indexes
01908  * without bothering to call this, because they know they don't have any
01909  * such expressions to deal with.
01910  */
01911 IndexStmt *
01912 transformIndexStmt(IndexStmt *stmt, const char *queryString)
01913 {
01914     Relation    rel;
01915     ParseState *pstate;
01916     RangeTblEntry *rte;
01917     ListCell   *l;
01918 
01919     /*
01920      * We must not scribble on the passed-in IndexStmt, so copy it.  (This is
01921      * overkill, but easy.)
01922      */
01923     stmt = (IndexStmt *) copyObject(stmt);
01924 
01925     /*
01926      * Open the parent table with appropriate locking.  We must do this
01927      * because addRangeTableEntry() would acquire only AccessShareLock,
01928      * leaving DefineIndex() needing to do a lock upgrade with consequent risk
01929      * of deadlock.  Make sure this stays in sync with the type of lock
01930      * DefineIndex() wants. If we are being called by ALTER TABLE, we will
01931      * already hold a higher lock.
01932      */
01933     rel = heap_openrv(stmt->relation,
01934                   (stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock));
01935 
01936     /* Set up pstate */
01937     pstate = make_parsestate(NULL);
01938     pstate->p_sourcetext = queryString;
01939 
01940     /*
01941      * Put the parent table into the rtable so that the expressions can refer
01942      * to its fields without qualification.
01943      */
01944     rte = addRangeTableEntry(pstate, stmt->relation, NULL, false, true);
01945 
01946     /* no to join list, yes to namespaces */
01947     addRTEtoQuery(pstate, rte, false, true, true);
01948 
01949     /* take care of the where clause */
01950     if (stmt->whereClause)
01951     {
01952         stmt->whereClause = transformWhereClause(pstate,
01953                                                  stmt->whereClause,
01954                                                  EXPR_KIND_INDEX_PREDICATE,
01955                                                  "WHERE");
01956         /* we have to fix its collations too */
01957         assign_expr_collations(pstate, stmt->whereClause);
01958     }
01959 
01960     /* take care of any index expressions */
01961     foreach(l, stmt->indexParams)
01962     {
01963         IndexElem  *ielem = (IndexElem *) lfirst(l);
01964 
01965         if (ielem->expr)
01966         {
01967             /* Extract preliminary index col name before transforming expr */
01968             if (ielem->indexcolname == NULL)
01969                 ielem->indexcolname = FigureIndexColname(ielem->expr);
01970 
01971             /* Now do parse transformation of the expression */
01972             ielem->expr = transformExpr(pstate, ielem->expr,
01973                                         EXPR_KIND_INDEX_EXPRESSION);
01974 
01975             /* We have to fix its collations too */
01976             assign_expr_collations(pstate, ielem->expr);
01977 
01978             /*
01979              * transformExpr() should have already rejected subqueries,
01980              * aggregates, and window functions, based on the EXPR_KIND_ for
01981              * an index expression.
01982              *
01983              * Also reject expressions returning sets; this is for consistency
01984              * with what transformWhereClause() checks for the predicate.
01985              * DefineIndex() will make more checks.
01986              */
01987             if (expression_returns_set(ielem->expr))
01988                 ereport(ERROR,
01989                         (errcode(ERRCODE_DATATYPE_MISMATCH),
01990                          errmsg("index expression cannot return a set")));
01991         }
01992     }
01993 
01994     /*
01995      * Check that only the base rel is mentioned.  (This should be dead code
01996      * now that add_missing_from is history.)
01997      */
01998     if (list_length(pstate->p_rtable) != 1)
01999         ereport(ERROR,
02000                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
02001                  errmsg("index expressions and predicates can refer only to the table being indexed")));
02002 
02003     free_parsestate(pstate);
02004 
02005     /* Close relation, but keep the lock */
02006     heap_close(rel, NoLock);
02007 
02008     return stmt;
02009 }
02010 
02011 
02012 /*
02013  * transformRuleStmt -
02014  *    transform a CREATE RULE Statement. The action is a list of parse
02015  *    trees which is transformed into a list of query trees, and we also
02016  *    transform the WHERE clause if any.
02017  *
02018  * actions and whereClause are output parameters that receive the
02019  * transformed results.
02020  *
02021  * Note that we must not scribble on the passed-in RuleStmt, so we do
02022  * copyObject() on the actions and WHERE clause.
02023  */
02024 void
02025 transformRuleStmt(RuleStmt *stmt, const char *queryString,
02026                   List **actions, Node **whereClause)
02027 {
02028     Relation    rel;
02029     ParseState *pstate;
02030     RangeTblEntry *oldrte;
02031     RangeTblEntry *newrte;
02032 
02033     /*
02034      * To avoid deadlock, make sure the first thing we do is grab
02035      * AccessExclusiveLock on the target relation.  This will be needed by
02036      * DefineQueryRewrite(), and we don't want to grab a lesser lock
02037      * beforehand.
02038      */
02039     rel = heap_openrv(stmt->relation, AccessExclusiveLock);
02040 
02041     if (rel->rd_rel->relkind == RELKIND_MATVIEW)
02042         ereport(ERROR,
02043                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02044                  errmsg("rules on materialized views are not supported")));
02045 
02046     /* Set up pstate */
02047     pstate = make_parsestate(NULL);
02048     pstate->p_sourcetext = queryString;
02049 
02050     /*
02051      * NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' equal to 2.
02052      * Set up their RTEs in the main pstate for use in parsing the rule
02053      * qualification.
02054      */
02055     oldrte = addRangeTableEntryForRelation(pstate, rel,
02056                                            makeAlias("old", NIL),
02057                                            false, false);
02058     newrte = addRangeTableEntryForRelation(pstate, rel,
02059                                            makeAlias("new", NIL),
02060                                            false, false);
02061     /* Must override addRangeTableEntry's default access-check flags */
02062     oldrte->requiredPerms = 0;
02063     newrte->requiredPerms = 0;
02064 
02065     /*
02066      * They must be in the namespace too for lookup purposes, but only add the
02067      * one(s) that are relevant for the current kind of rule.  In an UPDATE
02068      * rule, quals must refer to OLD.field or NEW.field to be unambiguous, but
02069      * there's no need to be so picky for INSERT & DELETE.  We do not add them
02070      * to the joinlist.
02071      */
02072     switch (stmt->event)
02073     {
02074         case CMD_SELECT:
02075             addRTEtoQuery(pstate, oldrte, false, true, true);
02076             break;
02077         case CMD_UPDATE:
02078             addRTEtoQuery(pstate, oldrte, false, true, true);
02079             addRTEtoQuery(pstate, newrte, false, true, true);
02080             break;
02081         case CMD_INSERT:
02082             addRTEtoQuery(pstate, newrte, false, true, true);
02083             break;
02084         case CMD_DELETE:
02085             addRTEtoQuery(pstate, oldrte, false, true, true);
02086             break;
02087         default:
02088             elog(ERROR, "unrecognized event type: %d",
02089                  (int) stmt->event);
02090             break;
02091     }
02092 
02093     /* take care of the where clause */
02094     *whereClause = transformWhereClause(pstate,
02095                                       (Node *) copyObject(stmt->whereClause),
02096                                         EXPR_KIND_WHERE,
02097                                         "WHERE");
02098     /* we have to fix its collations too */
02099     assign_expr_collations(pstate, *whereClause);
02100 
02101     /* this is probably dead code without add_missing_from: */
02102     if (list_length(pstate->p_rtable) != 2)     /* naughty, naughty... */
02103         ereport(ERROR,
02104                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02105                  errmsg("rule WHERE condition cannot contain references to other relations")));
02106 
02107     /*
02108      * 'instead nothing' rules with a qualification need a query rangetable so
02109      * the rewrite handler can add the negated rule qualification to the
02110      * original query. We create a query with the new command type CMD_NOTHING
02111      * here that is treated specially by the rewrite system.
02112      */
02113     if (stmt->actions == NIL)
02114     {
02115         Query      *nothing_qry = makeNode(Query);
02116 
02117         nothing_qry->commandType = CMD_NOTHING;
02118         nothing_qry->rtable = pstate->p_rtable;
02119         nothing_qry->jointree = makeFromExpr(NIL, NULL);        /* no join wanted */
02120 
02121         *actions = list_make1(nothing_qry);
02122     }
02123     else
02124     {
02125         ListCell   *l;
02126         List       *newactions = NIL;
02127 
02128         /*
02129          * transform each statement, like parse_sub_analyze()
02130          */
02131         foreach(l, stmt->actions)
02132         {
02133             Node       *action = (Node *) lfirst(l);
02134             ParseState *sub_pstate = make_parsestate(NULL);
02135             Query      *sub_qry,
02136                        *top_subqry;
02137             bool        has_old,
02138                         has_new;
02139 
02140             /*
02141              * Since outer ParseState isn't parent of inner, have to pass down
02142              * the query text by hand.
02143              */
02144             sub_pstate->p_sourcetext = queryString;
02145 
02146             /*
02147              * Set up OLD/NEW in the rtable for this statement.  The entries
02148              * are added only to relnamespace, not varnamespace, because we
02149              * don't want them to be referred to by unqualified field names
02150              * nor "*" in the rule actions.  We decide later whether to put
02151              * them in the joinlist.
02152              */
02153             oldrte = addRangeTableEntryForRelation(sub_pstate, rel,
02154                                                    makeAlias("old", NIL),
02155                                                    false, false);
02156             newrte = addRangeTableEntryForRelation(sub_pstate, rel,
02157                                                    makeAlias("new", NIL),
02158                                                    false, false);
02159             oldrte->requiredPerms = 0;
02160             newrte->requiredPerms = 0;
02161             addRTEtoQuery(sub_pstate, oldrte, false, true, false);
02162             addRTEtoQuery(sub_pstate, newrte, false, true, false);
02163 
02164             /* Transform the rule action statement */
02165             top_subqry = transformStmt(sub_pstate,
02166                                        (Node *) copyObject(action));
02167 
02168             /*
02169              * We cannot support utility-statement actions (eg NOTIFY) with
02170              * nonempty rule WHERE conditions, because there's no way to make
02171              * the utility action execute conditionally.
02172              */
02173             if (top_subqry->commandType == CMD_UTILITY &&
02174                 *whereClause != NULL)
02175                 ereport(ERROR,
02176                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02177                          errmsg("rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions")));
02178 
02179             /*
02180              * If the action is INSERT...SELECT, OLD/NEW have been pushed down
02181              * into the SELECT, and that's what we need to look at. (Ugly
02182              * kluge ... try to fix this when we redesign querytrees.)
02183              */
02184             sub_qry = getInsertSelectQuery(top_subqry, NULL);
02185 
02186             /*
02187              * If the sub_qry is a setop, we cannot attach any qualifications
02188              * to it, because the planner won't notice them.  This could
02189              * perhaps be relaxed someday, but for now, we may as well reject
02190              * such a rule immediately.
02191              */
02192             if (sub_qry->setOperations != NULL && *whereClause != NULL)
02193                 ereport(ERROR,
02194                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02195                          errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
02196 
02197             /*
02198              * Validate action's use of OLD/NEW, qual too
02199              */
02200             has_old =
02201                 rangeTableEntry_used((Node *) sub_qry, PRS2_OLD_VARNO, 0) ||
02202                 rangeTableEntry_used(*whereClause, PRS2_OLD_VARNO, 0);
02203             has_new =
02204                 rangeTableEntry_used((Node *) sub_qry, PRS2_NEW_VARNO, 0) ||
02205                 rangeTableEntry_used(*whereClause, PRS2_NEW_VARNO, 0);
02206 
02207             switch (stmt->event)
02208             {
02209                 case CMD_SELECT:
02210                     if (has_old)
02211                         ereport(ERROR,
02212                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02213                                  errmsg("ON SELECT rule cannot use OLD")));
02214                     if (has_new)
02215                         ereport(ERROR,
02216                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02217                                  errmsg("ON SELECT rule cannot use NEW")));
02218                     break;
02219                 case CMD_UPDATE:
02220                     /* both are OK */
02221                     break;
02222                 case CMD_INSERT:
02223                     if (has_old)
02224                         ereport(ERROR,
02225                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02226                                  errmsg("ON INSERT rule cannot use OLD")));
02227                     break;
02228                 case CMD_DELETE:
02229                     if (has_new)
02230                         ereport(ERROR,
02231                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
02232                                  errmsg("ON DELETE rule cannot use NEW")));
02233                     break;
02234                 default:
02235                     elog(ERROR, "unrecognized event type: %d",
02236                          (int) stmt->event);
02237                     break;
02238             }
02239 
02240             /*
02241              * OLD/NEW are not allowed in WITH queries, because they would
02242              * amount to outer references for the WITH, which we disallow.
02243              * However, they were already in the outer rangetable when we
02244              * analyzed the query, so we have to check.
02245              *
02246              * Note that in the INSERT...SELECT case, we need to examine the
02247              * CTE lists of both top_subqry and sub_qry.
02248              *
02249              * Note that we aren't digging into the body of the query looking
02250              * for WITHs in nested sub-SELECTs.  A WITH down there can
02251              * legitimately refer to OLD/NEW, because it'd be an
02252              * indirect-correlated outer reference.
02253              */
02254             if (rangeTableEntry_used((Node *) top_subqry->cteList,
02255                                      PRS2_OLD_VARNO, 0) ||
02256                 rangeTableEntry_used((Node *) sub_qry->cteList,
02257                                      PRS2_OLD_VARNO, 0))
02258                 ereport(ERROR,
02259                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02260                          errmsg("cannot refer to OLD within WITH query")));
02261             if (rangeTableEntry_used((Node *) top_subqry->cteList,
02262                                      PRS2_NEW_VARNO, 0) ||
02263                 rangeTableEntry_used((Node *) sub_qry->cteList,
02264                                      PRS2_NEW_VARNO, 0))
02265                 ereport(ERROR,
02266                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02267                          errmsg("cannot refer to NEW within WITH query")));
02268 
02269             /*
02270              * For efficiency's sake, add OLD to the rule action's jointree
02271              * only if it was actually referenced in the statement or qual.
02272              *
02273              * For INSERT, NEW is not really a relation (only a reference to
02274              * the to-be-inserted tuple) and should never be added to the
02275              * jointree.
02276              *
02277              * For UPDATE, we treat NEW as being another kind of reference to
02278              * OLD, because it represents references to *transformed* tuples
02279              * of the existing relation.  It would be wrong to enter NEW
02280              * separately in the jointree, since that would cause a double
02281              * join of the updated relation.  It's also wrong to fail to make
02282              * a jointree entry if only NEW and not OLD is mentioned.
02283              */
02284             if (has_old || (has_new && stmt->event == CMD_UPDATE))
02285             {
02286                 /*
02287                  * If sub_qry is a setop, manipulating its jointree will do no
02288                  * good at all, because the jointree is dummy. (This should be
02289                  * a can't-happen case because of prior tests.)
02290                  */
02291                 if (sub_qry->setOperations != NULL)
02292                     ereport(ERROR,
02293                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02294                              errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
02295                 /* hack so we can use addRTEtoQuery() */
02296                 sub_pstate->p_rtable = sub_qry->rtable;
02297                 sub_pstate->p_joinlist = sub_qry->jointree->fromlist;
02298                 addRTEtoQuery(sub_pstate, oldrte, true, false, false);
02299                 sub_qry->jointree->fromlist = sub_pstate->p_joinlist;
02300             }
02301 
02302             newactions = lappend(newactions, top_subqry);
02303 
02304             free_parsestate(sub_pstate);
02305         }
02306 
02307         *actions = newactions;
02308     }
02309 
02310     free_parsestate(pstate);
02311 
02312     /* Close relation, but keep the exclusive lock */
02313     heap_close(rel, NoLock);
02314 }
02315 
02316 
02317 /*
02318  * transformAlterTableStmt -
02319  *      parse analysis for ALTER TABLE
02320  *
02321  * Returns a List of utility commands to be done in sequence.  One of these
02322  * will be the transformed AlterTableStmt, but there may be additional actions
02323  * to be done before and after the actual AlterTable() call.
02324  */
02325 List *
02326 transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
02327 {
02328     Relation    rel;
02329     ParseState *pstate;
02330     CreateStmtContext cxt;
02331     List       *result;
02332     List       *save_alist;
02333     ListCell   *lcmd,
02334                *l;
02335     List       *newcmds = NIL;
02336     bool        skipValidation = true;
02337     AlterTableCmd *newcmd;
02338     LOCKMODE    lockmode;
02339 
02340     /*
02341      * We must not scribble on the passed-in AlterTableStmt, so copy it. (This
02342      * is overkill, but easy.)
02343      */
02344     stmt = (AlterTableStmt *) copyObject(stmt);
02345 
02346     /*
02347      * Determine the appropriate lock level for this list of subcommands.
02348      */
02349     lockmode = AlterTableGetLockLevel(stmt->cmds);
02350 
02351     /*
02352      * Acquire appropriate lock on the target relation, which will be held
02353      * until end of transaction.  This ensures any decisions we make here
02354      * based on the state of the relation will still be good at execution. We
02355      * must get lock now because execution will later require it; taking a
02356      * lower grade lock now and trying to upgrade later risks deadlock.  Any
02357      * new commands we add after this must not upgrade the lock level
02358      * requested here.
02359      */
02360     rel = relation_openrv_extended(stmt->relation, lockmode, stmt->missing_ok);
02361     if (rel == NULL)
02362     {
02363         /* this message is consistent with relation_openrv */
02364         ereport(NOTICE,
02365                 (errmsg("relation \"%s\" does not exist, skipping",
02366                         stmt->relation->relname)));
02367         return NIL;
02368     }
02369 
02370     /* Set up pstate and CreateStmtContext */
02371     pstate = make_parsestate(NULL);
02372     pstate->p_sourcetext = queryString;
02373 
02374     cxt.pstate = pstate;
02375     if (stmt->relkind == OBJECT_FOREIGN_TABLE)
02376     {
02377         cxt.stmtType = "ALTER FOREIGN TABLE";
02378         cxt.isforeign = true;
02379     }
02380     else
02381     {
02382         cxt.stmtType = "ALTER TABLE";
02383         cxt.isforeign = false;
02384     }
02385     cxt.relation = stmt->relation;
02386     cxt.rel = rel;
02387     cxt.inhRelations = NIL;
02388     cxt.isalter = true;
02389     cxt.hasoids = false;        /* need not be right */
02390     cxt.columns = NIL;
02391     cxt.ckconstraints = NIL;
02392     cxt.fkconstraints = NIL;
02393     cxt.ixconstraints = NIL;
02394     cxt.inh_indexes = NIL;
02395     cxt.blist = NIL;
02396     cxt.alist = NIL;
02397     cxt.pkey = NULL;
02398 
02399     /*
02400      * The only subtypes that currently require parse transformation handling
02401      * are ADD COLUMN and ADD CONSTRAINT.  These largely re-use code from
02402      * CREATE TABLE.
02403      */
02404     foreach(lcmd, stmt->cmds)
02405     {
02406         AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
02407 
02408         switch (cmd->subtype)
02409         {
02410             case AT_AddColumn:
02411             case AT_AddColumnToView:
02412                 {
02413                     ColumnDef  *def = (ColumnDef *) cmd->def;
02414 
02415                     Assert(IsA(def, ColumnDef));
02416                     transformColumnDefinition(&cxt, def);
02417 
02418                     /*
02419                      * If the column has a non-null default, we can't skip
02420                      * validation of foreign keys.
02421                      */
02422                     if (def->raw_default != NULL)
02423                         skipValidation = false;
02424 
02425                     /*
02426                      * All constraints are processed in other ways. Remove the
02427                      * original list
02428                      */
02429                     def->constraints = NIL;
02430 
02431                     newcmds = lappend(newcmds, cmd);
02432                     break;
02433                 }
02434             case AT_AddConstraint:
02435 
02436                 /*
02437                  * The original AddConstraint cmd node doesn't go to newcmds
02438                  */
02439                 if (IsA(cmd->def, Constraint))
02440                 {
02441                     transformTableConstraint(&cxt, (Constraint *) cmd->def);
02442                     if (((Constraint *) cmd->def)->contype == CONSTR_FOREIGN)
02443                         skipValidation = false;
02444                 }
02445                 else
02446                     elog(ERROR, "unrecognized node type: %d",
02447                          (int) nodeTag(cmd->def));
02448                 break;
02449 
02450             case AT_ProcessedConstraint:
02451 
02452                 /*
02453                  * Already-transformed ADD CONSTRAINT, so just make it look
02454                  * like the standard case.
02455                  */
02456                 cmd->subtype = AT_AddConstraint;
02457                 newcmds = lappend(newcmds, cmd);
02458                 break;
02459 
02460             default:
02461                 newcmds = lappend(newcmds, cmd);
02462                 break;
02463         }
02464     }
02465 
02466     /*
02467      * transformIndexConstraints wants cxt.alist to contain only index
02468      * statements, so transfer anything we already have into save_alist
02469      * immediately.
02470      */
02471     save_alist = cxt.alist;
02472     cxt.alist = NIL;
02473 
02474     /* Postprocess index and FK constraints */
02475     transformIndexConstraints(&cxt);
02476 
02477     transformFKConstraints(&cxt, skipValidation, true);
02478 
02479     /*
02480      * Push any index-creation commands into the ALTER, so that they can be
02481      * scheduled nicely by tablecmds.c.  Note that tablecmds.c assumes that
02482      * the IndexStmt attached to an AT_AddIndex or AT_AddIndexConstraint
02483      * subcommand has already been through transformIndexStmt.
02484      */
02485     foreach(l, cxt.alist)
02486     {
02487         IndexStmt  *idxstmt = (IndexStmt *) lfirst(l);
02488 
02489         Assert(IsA(idxstmt, IndexStmt));
02490         idxstmt = transformIndexStmt(idxstmt, queryString);
02491         newcmd = makeNode(AlterTableCmd);
02492         newcmd->subtype = OidIsValid(idxstmt->indexOid) ? AT_AddIndexConstraint : AT_AddIndex;
02493         newcmd->def = (Node *) idxstmt;
02494         newcmds = lappend(newcmds, newcmd);
02495     }
02496     cxt.alist = NIL;
02497 
02498     /* Append any CHECK or FK constraints to the commands list */
02499     foreach(l, cxt.ckconstraints)
02500     {
02501         newcmd = makeNode(AlterTableCmd);
02502         newcmd->subtype = AT_AddConstraint;
02503         newcmd->def = (Node *) lfirst(l);
02504         newcmds = lappend(newcmds, newcmd);
02505     }
02506     foreach(l, cxt.fkconstraints)
02507     {
02508         newcmd = makeNode(AlterTableCmd);
02509         newcmd->subtype = AT_AddConstraint;
02510         newcmd->def = (Node *) lfirst(l);
02511         newcmds = lappend(newcmds, newcmd);
02512     }
02513 
02514     /* Close rel but keep lock */
02515     relation_close(rel, NoLock);
02516 
02517     /*
02518      * Output results.
02519      */
02520     stmt->cmds = newcmds;
02521 
02522     result = lappend(cxt.blist, stmt);
02523     result = list_concat(result, cxt.alist);
02524     result = list_concat(result, save_alist);
02525 
02526     return result;
02527 }
02528 
02529 
02530 /*
02531  * Preprocess a list of column constraint clauses
02532  * to attach constraint attributes to their primary constraint nodes
02533  * and detect inconsistent/misplaced constraint attributes.
02534  *
02535  * NOTE: currently, attributes are only supported for FOREIGN KEY, UNIQUE,
02536  * EXCLUSION, and PRIMARY KEY constraints, but someday they ought to be
02537  * supported for other constraint types.
02538  */
02539 static void
02540 transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList)
02541 {
02542     Constraint *lastprimarycon = NULL;
02543     bool        saw_deferrability = false;
02544     bool        saw_initially = false;
02545     ListCell   *clist;
02546 
02547 #define SUPPORTS_ATTRS(node)                \
02548     ((node) != NULL &&                      \
02549      ((node)->contype == CONSTR_PRIMARY ||  \
02550       (node)->contype == CONSTR_UNIQUE ||   \
02551       (node)->contype == CONSTR_EXCLUSION || \
02552       (node)->contype == CONSTR_FOREIGN))
02553 
02554     foreach(clist, constraintList)
02555     {
02556         Constraint *con = (Constraint *) lfirst(clist);
02557 
02558         if (!IsA(con, Constraint))
02559             elog(ERROR, "unrecognized node type: %d",
02560                  (int) nodeTag(con));
02561         switch (con->contype)
02562         {
02563             case CONSTR_ATTR_DEFERRABLE:
02564                 if (!SUPPORTS_ATTRS(lastprimarycon))
02565                     ereport(ERROR,
02566                             (errcode(ERRCODE_SYNTAX_ERROR),
02567                              errmsg("misplaced DEFERRABLE clause"),
02568                              parser_errposition(cxt->pstate, con->location)));
02569                 if (saw_deferrability)
02570                     ereport(ERROR,
02571                             (errcode(ERRCODE_SYNTAX_ERROR),
02572                              errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
02573                              parser_errposition(cxt->pstate, con->location)));
02574                 saw_deferrability = true;
02575                 lastprimarycon->deferrable = true;
02576                 break;
02577 
02578             case CONSTR_ATTR_NOT_DEFERRABLE:
02579                 if (!SUPPORTS_ATTRS(lastprimarycon))
02580                     ereport(ERROR,
02581                             (errcode(ERRCODE_SYNTAX_ERROR),
02582                              errmsg("misplaced NOT DEFERRABLE clause"),
02583                              parser_errposition(cxt->pstate, con->location)));
02584                 if (saw_deferrability)
02585                     ereport(ERROR,
02586                             (errcode(ERRCODE_SYNTAX_ERROR),
02587                              errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
02588                              parser_errposition(cxt->pstate, con->location)));
02589                 saw_deferrability = true;
02590                 lastprimarycon->deferrable = false;
02591                 if (saw_initially &&
02592                     lastprimarycon->initdeferred)
02593                     ereport(ERROR,
02594                             (errcode(ERRCODE_SYNTAX_ERROR),
02595                              errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
02596                              parser_errposition(cxt->pstate, con->location)));
02597                 break;
02598 
02599             case CONSTR_ATTR_DEFERRED:
02600                 if (!SUPPORTS_ATTRS(lastprimarycon))
02601                     ereport(ERROR,
02602                             (errcode(ERRCODE_SYNTAX_ERROR),
02603                              errmsg("misplaced INITIALLY DEFERRED clause"),
02604                              parser_errposition(cxt->pstate, con->location)));
02605                 if (saw_initially)
02606                     ereport(ERROR,
02607                             (errcode(ERRCODE_SYNTAX_ERROR),
02608                              errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
02609                              parser_errposition(cxt->pstate, con->location)));
02610                 saw_initially = true;
02611                 lastprimarycon->initdeferred = true;
02612 
02613                 /*
02614                  * If only INITIALLY DEFERRED appears, assume DEFERRABLE
02615                  */
02616                 if (!saw_deferrability)
02617                     lastprimarycon->deferrable = true;
02618                 else if (!lastprimarycon->deferrable)
02619                     ereport(ERROR,
02620                             (errcode(ERRCODE_SYNTAX_ERROR),
02621                              errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
02622                              parser_errposition(cxt->pstate, con->location)));
02623                 break;
02624 
02625             case CONSTR_ATTR_IMMEDIATE:
02626                 if (!SUPPORTS_ATTRS(lastprimarycon))
02627                     ereport(ERROR,
02628                             (errcode(ERRCODE_SYNTAX_ERROR),
02629                              errmsg("misplaced INITIALLY IMMEDIATE clause"),
02630                              parser_errposition(cxt->pstate, con->location)));
02631                 if (saw_initially)
02632                     ereport(ERROR,
02633                             (errcode(ERRCODE_SYNTAX_ERROR),
02634                              errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
02635                              parser_errposition(cxt->pstate, con->location)));
02636                 saw_initially = true;
02637                 lastprimarycon->initdeferred = false;
02638                 break;
02639 
02640             default:
02641                 /* Otherwise it's not an attribute */
02642                 lastprimarycon = con;
02643                 /* reset flags for new primary node */
02644                 saw_deferrability = false;
02645                 saw_initially = false;
02646                 break;
02647         }
02648     }
02649 }
02650 
02651 /*
02652  * Special handling of type definition for a column
02653  */
02654 static void
02655 transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
02656 {
02657     /*
02658      * All we really need to do here is verify that the type is valid,
02659      * including any collation spec that might be present.
02660      */
02661     Type        ctype = typenameType(cxt->pstate, column->typeName, NULL);
02662 
02663     if (column->collClause)
02664     {
02665         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(ctype);
02666 
02667         LookupCollation(cxt->pstate,
02668                         column->collClause->collname,
02669                         column->collClause->location);
02670         /* Complain if COLLATE is applied to an uncollatable type */
02671         if (!OidIsValid(typtup->typcollation))
02672             ereport(ERROR,
02673                     (errcode(ERRCODE_DATATYPE_MISMATCH),
02674                      errmsg("collations are not supported by type %s",
02675                             format_type_be(HeapTupleGetOid(ctype))),
02676                      parser_errposition(cxt->pstate,
02677                                         column->collClause->location)));
02678     }
02679 
02680     ReleaseSysCache(ctype);
02681 }
02682 
02683 
02684 /*
02685  * transformCreateSchemaStmt -
02686  *    analyzes the CREATE SCHEMA statement
02687  *
02688  * Split the schema element list into individual commands and place
02689  * them in the result list in an order such that there are no forward
02690  * references (e.g. GRANT to a table created later in the list). Note
02691  * that the logic we use for determining forward references is
02692  * presently quite incomplete.
02693  *
02694  * SQL also allows constraints to make forward references, so thumb through
02695  * the table columns and move forward references to a posterior alter-table
02696  * command.
02697  *
02698  * The result is a list of parse nodes that still need to be analyzed ---
02699  * but we can't analyze the later commands until we've executed the earlier
02700  * ones, because of possible inter-object references.
02701  *
02702  * Note: this breaks the rules a little bit by modifying schema-name fields
02703  * within passed-in structs.  However, the transformation would be the same
02704  * if done over, so it should be all right to scribble on the input to this
02705  * extent.
02706  */
02707 List *
02708 transformCreateSchemaStmt(CreateSchemaStmt *stmt)
02709 {
02710     CreateSchemaStmtContext cxt;
02711     List       *result;
02712     ListCell   *elements;
02713 
02714     cxt.stmtType = "CREATE SCHEMA";
02715     cxt.schemaname = stmt->schemaname;
02716     cxt.authid = stmt->authid;
02717     cxt.sequences = NIL;
02718     cxt.tables = NIL;
02719     cxt.views = NIL;
02720     cxt.indexes = NIL;
02721     cxt.triggers = NIL;
02722     cxt.grants = NIL;
02723 
02724     /*
02725      * Run through each schema element in the schema element list. Separate
02726      * statements by type, and do preliminary analysis.
02727      */
02728     foreach(elements, stmt->schemaElts)
02729     {
02730         Node       *element = lfirst(elements);
02731 
02732         switch (nodeTag(element))
02733         {
02734             case T_CreateSeqStmt:
02735                 {
02736                     CreateSeqStmt *elp = (CreateSeqStmt *) element;
02737 
02738                     setSchemaName(cxt.schemaname, &elp->sequence->schemaname);
02739                     cxt.sequences = lappend(cxt.sequences, element);
02740                 }
02741                 break;
02742 
02743             case T_CreateStmt:
02744                 {
02745                     CreateStmt *elp = (CreateStmt *) element;
02746 
02747                     setSchemaName(cxt.schemaname, &elp->relation->schemaname);
02748 
02749                     /*
02750                      * XXX todo: deal with constraints
02751                      */
02752                     cxt.tables = lappend(cxt.tables, element);
02753                 }
02754                 break;
02755 
02756             case T_ViewStmt:
02757                 {
02758                     ViewStmt   *elp = (ViewStmt *) element;
02759 
02760                     setSchemaName(cxt.schemaname, &elp->view->schemaname);
02761 
02762                     /*
02763                      * XXX todo: deal with references between views
02764                      */
02765                     cxt.views = lappend(cxt.views, element);
02766                 }
02767                 break;
02768 
02769             case T_IndexStmt:
02770                 {
02771                     IndexStmt  *elp = (IndexStmt *) element;
02772 
02773                     setSchemaName(cxt.schemaname, &elp->relation->schemaname);
02774                     cxt.indexes = lappend(cxt.indexes, element);
02775                 }
02776                 break;
02777 
02778             case T_CreateTrigStmt:
02779                 {
02780                     CreateTrigStmt *elp = (CreateTrigStmt *) element;
02781 
02782                     setSchemaName(cxt.schemaname, &elp->relation->schemaname);
02783                     cxt.triggers = lappend(cxt.triggers, element);
02784                 }
02785                 break;
02786 
02787             case T_GrantStmt:
02788                 cxt.grants = lappend(cxt.grants, element);
02789                 break;
02790 
02791             default:
02792                 elog(ERROR, "unrecognized node type: %d",
02793                      (int) nodeTag(element));
02794         }
02795     }
02796 
02797     result = NIL;
02798     result = list_concat(result, cxt.sequences);
02799     result = list_concat(result, cxt.tables);
02800     result = list_concat(result, cxt.views);
02801     result = list_concat(result, cxt.indexes);
02802     result = list_concat(result, cxt.triggers);
02803     result = list_concat(result, cxt.grants);
02804 
02805     return result;
02806 }
02807 
02808 /*
02809  * setSchemaName
02810  *      Set or check schema name in an element of a CREATE SCHEMA command
02811  */
02812 static void
02813 setSchemaName(char *context_schema, char **stmt_schema_name)
02814 {
02815     if (*stmt_schema_name == NULL)
02816         *stmt_schema_name = context_schema;
02817     else if (strcmp(context_schema, *stmt_schema_name) != 0)
02818         ereport(ERROR,
02819                 (errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
02820                  errmsg("CREATE specifies a schema (%s) "
02821                         "different from the one being created (%s)",
02822                         *stmt_schema_name, context_schema)));
02823 }