LCOV - differential code coverage report
Current view: top level - src/backend/parser - parse_utilcmd.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 89.5 % 1589 1422 3 66 89 9 48 846 71 457 107 866 3 33
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 29 29 29 28 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * parse_utilcmd.c
       4                 :  *    Perform parse analysis work for various utility commands
       5                 :  *
       6                 :  * Formerly we did this work during parse_analyze_*() in analyze.c.  However
       7                 :  * that is fairly unsafe in the presence of querytree caching, since any
       8                 :  * database state that we depend on in making the transformations might be
       9                 :  * obsolete by the time the utility command is executed; and utility commands
      10                 :  * have no infrastructure for holding locks or rechecking plan validity.
      11                 :  * Hence these functions are now called at the start of execution of their
      12                 :  * respective utility commands.
      13                 :  *
      14                 :  *
      15                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
      16                 :  * Portions Copyright (c) 1994, Regents of the University of California
      17                 :  *
      18                 :  *  src/backend/parser/parse_utilcmd.c
      19                 :  *
      20                 :  *-------------------------------------------------------------------------
      21                 :  */
      22                 : 
      23                 : #include "postgres.h"
      24                 : 
      25                 : #include "access/amapi.h"
      26                 : #include "access/htup_details.h"
      27                 : #include "access/relation.h"
      28                 : #include "access/reloptions.h"
      29                 : #include "access/table.h"
      30                 : #include "access/toast_compression.h"
      31                 : #include "catalog/dependency.h"
      32                 : #include "catalog/heap.h"
      33                 : #include "catalog/index.h"
      34                 : #include "catalog/namespace.h"
      35                 : #include "catalog/pg_am.h"
      36                 : #include "catalog/pg_collation.h"
      37                 : #include "catalog/pg_constraint.h"
      38                 : #include "catalog/pg_opclass.h"
      39                 : #include "catalog/pg_operator.h"
      40                 : #include "catalog/pg_statistic_ext.h"
      41                 : #include "catalog/pg_type.h"
      42                 : #include "commands/comment.h"
      43                 : #include "commands/defrem.h"
      44                 : #include "commands/sequence.h"
      45                 : #include "commands/tablecmds.h"
      46                 : #include "commands/tablespace.h"
      47                 : #include "miscadmin.h"
      48                 : #include "nodes/makefuncs.h"
      49                 : #include "nodes/nodeFuncs.h"
      50                 : #include "optimizer/optimizer.h"
      51                 : #include "parser/analyze.h"
      52                 : #include "parser/parse_clause.h"
      53                 : #include "parser/parse_coerce.h"
      54                 : #include "parser/parse_collate.h"
      55                 : #include "parser/parse_expr.h"
      56                 : #include "parser/parse_relation.h"
      57                 : #include "parser/parse_target.h"
      58                 : #include "parser/parse_type.h"
      59                 : #include "parser/parse_utilcmd.h"
      60                 : #include "parser/parser.h"
      61                 : #include "rewrite/rewriteManip.h"
      62                 : #include "utils/acl.h"
      63                 : #include "utils/builtins.h"
      64                 : #include "utils/lsyscache.h"
      65                 : #include "utils/partcache.h"
      66                 : #include "utils/rel.h"
      67                 : #include "utils/ruleutils.h"
      68                 : #include "utils/syscache.h"
      69                 : #include "utils/typcache.h"
      70                 : 
      71                 : 
      72                 : /* State shared by transformCreateStmt and its subroutines */
      73                 : typedef struct
      74                 : {
      75                 :     ParseState *pstate;         /* overall parser state */
      76                 :     const char *stmtType;       /* "CREATE [FOREIGN] TABLE" or "ALTER TABLE" */
      77                 :     RangeVar   *relation;       /* relation to create */
      78                 :     Relation    rel;            /* opened/locked rel, if ALTER */
      79                 :     List       *inhRelations;   /* relations to inherit from */
      80                 :     bool        isforeign;      /* true if CREATE/ALTER FOREIGN TABLE */
      81                 :     bool        isalter;        /* true if altering existing table */
      82                 :     List       *columns;        /* ColumnDef items */
      83                 :     List       *ckconstraints;  /* CHECK constraints */
      84                 :     List       *fkconstraints;  /* FOREIGN KEY constraints */
      85                 :     List       *ixconstraints;  /* index-creating constraints */
      86                 :     List       *nnconstraints;  /* NOT NULL constraints */
      87                 :     List       *likeclauses;    /* LIKE clauses that need post-processing */
      88                 :     List       *extstats;       /* cloned extended statistics */
      89                 :     List       *blist;          /* "before list" of things to do before
      90                 :                                  * creating the table */
      91                 :     List       *alist;          /* "after list" of things to do after creating
      92                 :                                  * the table */
      93                 :     IndexStmt  *pkey;           /* PRIMARY KEY index, if any */
      94                 :     bool        ispartitioned;  /* true if table is partitioned */
      95                 :     PartitionBoundSpec *partbound;  /* transformed FOR VALUES */
      96                 :     bool        ofType;         /* true if statement contains OF typename */
      97                 : } CreateStmtContext;
      98                 : 
      99                 : /* State shared by transformCreateSchemaStmt and its subroutines */
     100                 : typedef struct
     101                 : {
     102                 :     const char *stmtType;       /* "CREATE SCHEMA" or "ALTER SCHEMA" */
     103                 :     char       *schemaname;     /* name of schema */
     104                 :     RoleSpec   *authrole;       /* owner of schema */
     105                 :     List       *sequences;      /* CREATE SEQUENCE items */
     106                 :     List       *tables;         /* CREATE TABLE items */
     107                 :     List       *views;          /* CREATE VIEW items */
     108                 :     List       *indexes;        /* CREATE INDEX items */
     109                 :     List       *triggers;       /* CREATE TRIGGER items */
     110                 :     List       *grants;         /* GRANT items */
     111                 : } CreateSchemaStmtContext;
     112                 : 
     113                 : 
     114                 : static void transformColumnDefinition(CreateStmtContext *cxt,
     115                 :                                       ColumnDef *column);
     116                 : static void transformTableConstraint(CreateStmtContext *cxt,
     117                 :                                      Constraint *constraint);
     118                 : static void transformTableLikeClause(CreateStmtContext *cxt,
     119                 :                                      TableLikeClause *table_like_clause);
     120                 : static void transformOfType(CreateStmtContext *cxt,
     121                 :                             TypeName *ofTypename);
     122                 : static CreateStatsStmt *generateClonedExtStatsStmt(RangeVar *heapRel,
     123                 :                                                    Oid heapRelid, Oid source_statsid);
     124                 : static List *get_collation(Oid collation, Oid actual_datatype);
     125                 : static List *get_opclass(Oid opclass, Oid actual_datatype);
     126                 : static void transformIndexConstraints(CreateStmtContext *cxt);
     127                 : static IndexStmt *transformIndexConstraint(Constraint *constraint,
     128                 :                                            CreateStmtContext *cxt);
     129                 : static void transformExtendedStatistics(CreateStmtContext *cxt);
     130                 : static void transformFKConstraints(CreateStmtContext *cxt,
     131                 :                                    bool skipValidation,
     132                 :                                    bool isAddConstraint);
     133                 : static void transformCheckConstraints(CreateStmtContext *cxt,
     134                 :                                       bool skipValidation);
     135                 : static void transformConstraintAttrs(CreateStmtContext *cxt,
     136                 :                                      List *constraintList);
     137                 : static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column);
     138                 : static void setSchemaName(char *context_schema, char **stmt_schema_name);
     139                 : static void transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd);
     140                 : static List *transformPartitionRangeBounds(ParseState *pstate, List *blist,
     141                 :                                            Relation parent);
     142                 : static void validateInfiniteBounds(ParseState *pstate, List *blist);
     143                 : static Const *transformPartitionBoundValue(ParseState *pstate, Node *val,
     144                 :                                            const char *colName, Oid colType, int32 colTypmod,
     145                 :                                            Oid partCollation);
     146                 : 
     147                 : 
     148                 : /*
     149                 :  * transformCreateStmt -
     150                 :  *    parse analysis for CREATE TABLE
     151                 :  *
     152                 :  * Returns a List of utility commands to be done in sequence.  One of these
     153                 :  * will be the transformed CreateStmt, but there may be additional actions
     154                 :  * to be done before and after the actual DefineRelation() call.
     155                 :  * In addition to normal utility commands such as AlterTableStmt and
     156                 :  * IndexStmt, the result list may contain TableLikeClause(s), representing
     157                 :  * the need to perform additional parse analysis after DefineRelation().
     158                 :  *
     159                 :  * SQL allows constraints to be scattered all over, so thumb through
     160                 :  * the columns and collect all constraints into one place.
     161                 :  * If there are any implied indices (e.g. UNIQUE or PRIMARY KEY)
     162                 :  * then expand those into multiple IndexStmt blocks.
     163                 :  *    - thomas 1997-12-02
     164                 :  */
     165                 : List *
     166 GIC       17260 : transformCreateStmt(CreateStmt *stmt, const char *queryString)
     167 ECB             : {
     168                 :     ParseState *pstate;
     169                 :     CreateStmtContext cxt;
     170                 :     List       *result;
     171                 :     List       *save_alist;
     172                 :     ListCell   *elements;
     173                 :     Oid         namespaceid;
     174                 :     Oid         existing_relid;
     175                 :     ParseCallbackState pcbstate;
     176                 : 
     177                 :     /* Set up pstate */
     178 GIC       17260 :     pstate = make_parsestate(NULL);
     179 CBC       17260 :     pstate->p_sourcetext = queryString;
     180 ECB             : 
     181                 :     /*
     182                 :      * Look up the creation namespace.  This also checks permissions on the
     183                 :      * target namespace, locks it against concurrent drops, checks for a
     184                 :      * preexisting relation in that namespace with the same name, and updates
     185                 :      * stmt->relation->relpersistence if the selected namespace is temporary.
     186                 :      */
     187 GIC       17260 :     setup_parser_errposition_callback(&pcbstate, pstate,
     188 CBC       17260 :                                       stmt->relation->location);
     189 ECB             :     namespaceid =
     190 GIC       17260 :         RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock,
     191 ECB             :                                              &existing_relid);
     192 GIC       17254 :     cancel_parser_errposition_callback(&pcbstate);
     193 ECB             : 
     194                 :     /*
     195                 :      * If the relation already exists and the user specified "IF NOT EXISTS",
     196                 :      * bail out with a NOTICE.
     197                 :      */
     198 GIC       17254 :     if (stmt->if_not_exists && OidIsValid(existing_relid))
     199 ECB             :     {
     200                 :         /*
     201                 :          * If we are in an extension script, insist that the pre-existing
     202                 :          * object be a member of the extension, to avoid security risks.
     203                 :          */
     204                 :         ObjectAddress address;
     205                 : 
     206 GIC           5 :         ObjectAddressSet(address, RelationRelationId, existing_relid);
     207 CBC           5 :         checkMembershipInCurrentExtension(&address);
     208 ECB             : 
     209                 :         /* OK to skip */
     210 GIC           4 :         ereport(NOTICE,
     211 ECB             :                 (errcode(ERRCODE_DUPLICATE_TABLE),
     212                 :                  errmsg("relation \"%s\" already exists, skipping",
     213                 :                         stmt->relation->relname)));
     214 GIC           4 :         return NIL;
     215 ECB             :     }
     216                 : 
     217                 :     /*
     218                 :      * If the target relation name isn't schema-qualified, make it so.  This
     219                 :      * prevents some corner cases in which added-on rewritten commands might
     220                 :      * think they should apply to other relations that have the same name and
     221                 :      * are earlier in the search path.  But a local temp table is effectively
     222                 :      * specified to be in pg_temp, so no need for anything extra in that case.
     223                 :      */
     224 GIC       17249 :     if (stmt->relation->schemaname == NULL
     225 CBC       15870 :         && stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
     226           14817 :         stmt->relation->schemaname = get_namespace_name(namespaceid);
     227 ECB             : 
     228                 :     /* Set up CreateStmtContext */
     229 GIC       17249 :     cxt.pstate = pstate;
     230 CBC       17249 :     if (IsA(stmt, CreateForeignTableStmt))
     231 ECB             :     {
     232 GIC         219 :         cxt.stmtType = "CREATE FOREIGN TABLE";
     233 CBC         219 :         cxt.isforeign = true;
     234 ECB             :     }
     235                 :     else
     236                 :     {
     237 GIC       17030 :         cxt.stmtType = "CREATE TABLE";
     238 CBC       17030 :         cxt.isforeign = false;
     239 ECB             :     }
     240 GIC       17249 :     cxt.relation = stmt->relation;
     241 CBC       17249 :     cxt.rel = NULL;
     242           17249 :     cxt.inhRelations = stmt->inhRelations;
     243           17249 :     cxt.isalter = false;
     244           17249 :     cxt.columns = NIL;
     245           17249 :     cxt.ckconstraints = NIL;
     246           17249 :     cxt.fkconstraints = NIL;
     247           17249 :     cxt.ixconstraints = NIL;
     248 GNC       17249 :     cxt.nnconstraints = NIL;
     249 CBC       17249 :     cxt.likeclauses = NIL;
     250           17249 :     cxt.extstats = NIL;
     251           17249 :     cxt.blist = NIL;
     252           17249 :     cxt.alist = NIL;
     253           17249 :     cxt.pkey = NULL;
     254           17249 :     cxt.ispartitioned = stmt->partspec != NULL;
     255           17249 :     cxt.partbound = stmt->partbound;
     256           17249 :     cxt.ofType = (stmt->ofTypename != NULL);
     257 ECB             : 
     258 CBC       17249 :     Assert(!stmt->ofTypename || !stmt->inhRelations); /* grammar enforces */
     259                 : 
     260           17249 :     if (stmt->ofTypename)
     261 GIC          55 :         transformOfType(&cxt, stmt->ofTypename);
     262 ECB             : 
     263 CBC       17243 :     if (stmt->partspec)
     264                 :     {
     265            2187 :         if (stmt->inhRelations && !stmt->partbound)
     266 GIC           3 :             ereport(ERROR,
     267 ECB             :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
     268                 :                      errmsg("cannot create partitioned table as inheritance child")));
     269                 :     }
     270                 : 
     271                 :     /*
     272                 :      * Run through each primary element in the table creation clause. Separate
     273                 :      * column defs from constraints, and do preliminary analysis.
     274                 :      */
     275 GIC       52306 :     foreach(elements, stmt->tableElts)
     276                 :     {
     277 CBC       35151 :         Node       *element = lfirst(elements);
     278                 : 
     279           35151 :         switch (nodeTag(element))
     280                 :         {
     281           33904 :             case T_ColumnDef:
     282 GIC       33904 :                 transformColumnDefinition(&cxt, (ColumnDef *) element);
     283 CBC       33834 :                 break;
     284 ECB             : 
     285 CBC         899 :             case T_Constraint:
     286 GIC         899 :                 transformTableConstraint(&cxt, (Constraint *) element);
     287 CBC         890 :                 break;
     288 ECB             : 
     289 CBC         348 :             case T_TableLikeClause:
     290 GIC         348 :                 transformTableLikeClause(&cxt, (TableLikeClause *) element);
     291 CBC         342 :                 break;
     292 ECB             : 
     293 LBC           0 :             default:
     294 UIC           0 :                 elog(ERROR, "unrecognized node type: %d",
     295 EUB             :                      (int) nodeTag(element));
     296                 :                 break;
     297                 :         }
     298                 :     }
     299                 : 
     300                 :     /*
     301                 :      * Transfer anything we already have in cxt.alist into save_alist, to keep
     302                 :      * it separate from the output of transformIndexConstraints.  (This may
     303                 :      * not be necessary anymore, but we'll keep doing it to preserve the
     304                 :      * historical order of execution of the alist commands.)
     305                 :      */
     306 GIC       17155 :     save_alist = cxt.alist;
     307           17155 :     cxt.alist = NIL;
     308 ECB             : 
     309 CBC       17155 :     Assert(stmt->constraints == NIL);
     310                 : 
     311 ECB             :     /*
     312                 :      * Postprocess constraints that give rise to index definitions.
     313                 :      */
     314 GIC       17155 :     transformIndexConstraints(&cxt);
     315                 : 
     316 ECB             :     /*
     317                 :      * Re-consideration of LIKE clauses should happen after creation of
     318                 :      * indexes, but before creation of foreign keys.  This order is critical
     319                 :      * because a LIKE clause may attempt to create a primary key.  If there's
     320                 :      * also a pkey in the main CREATE TABLE list, creation of that will not
     321                 :      * check for a duplicate at runtime (since index_check_primary_key()
     322                 :      * expects that we rejected dups here).  Creation of the LIKE-generated
     323                 :      * pkey behaves like ALTER TABLE ADD, so it will check, but obviously that
     324                 :      * only works if it happens second.  On the other hand, we want to make
     325                 :      * pkeys before foreign key constraints, in case the user tries to make a
     326                 :      * self-referential FK.
     327                 :      */
     328 GIC       17155 :     cxt.alist = list_concat(cxt.alist, cxt.likeclauses);
     329                 : 
     330 ECB             :     /*
     331                 :      * Postprocess foreign-key constraints.
     332                 :      */
     333 GIC       17155 :     transformFKConstraints(&cxt, true, false);
     334                 : 
     335 ECB             :     /*
     336                 :      * Postprocess check constraints.
     337                 :      *
     338                 :      * For regular tables all constraints can be marked valid immediately,
     339                 :      * because the table is new therefore empty. Not so for foreign tables.
     340                 :      */
     341 GIC       17155 :     transformCheckConstraints(&cxt, !cxt.isforeign);
     342                 : 
     343 ECB             :     /*
     344                 :      * Postprocess extended statistics.
     345                 :      */
     346 GIC       17155 :     transformExtendedStatistics(&cxt);
     347                 : 
     348 ECB             :     /*
     349                 :      * Output results.
     350                 :      */
     351 GIC       17155 :     stmt->tableElts = cxt.columns;
     352           17155 :     stmt->constraints = cxt.ckconstraints;
     353 GNC       17155 :     stmt->nnconstraints = cxt.nnconstraints;
     354 ECB             : 
     355 CBC       17155 :     result = lappend(cxt.blist, stmt);
     356           17155 :     result = list_concat(result, cxt.alist);
     357 GIC       17155 :     result = list_concat(result, save_alist);
     358 ECB             : 
     359 CBC       17155 :     return result;
     360 ECB             : }
     361                 : 
     362                 : /*
     363                 :  * generateSerialExtraStmts
     364                 :  *      Generate CREATE SEQUENCE and ALTER SEQUENCE ... OWNED BY statements
     365                 :  *      to create the sequence for a serial or identity column.
     366                 :  *
     367                 :  * This includes determining the name the sequence will have.  The caller
     368                 :  * can ask to get back the name components by passing non-null pointers
     369                 :  * for snamespace_p and sname_p.
     370                 :  */
     371                 : static void
     372 GIC         505 : generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
     373                 :                          Oid seqtypid, List *seqoptions,
     374                 :                          bool for_identity, bool col_exists,
     375 ECB             :                          char **snamespace_p, char **sname_p)
     376                 : {
     377                 :     ListCell   *option;
     378 GIC         505 :     DefElem    *nameEl = NULL;
     379                 :     Oid         snamespaceid;
     380                 :     char       *snamespace;
     381 ECB             :     char       *sname;
     382                 :     CreateSeqStmt *seqstmt;
     383                 :     AlterSeqStmt *altseqstmt;
     384                 :     List       *attnamelist;
     385 GIC         505 :     int         nameEl_idx = -1;
     386                 : 
     387                 :     /* Make a copy of this as we may end up modifying it in the code below */
     388 CBC         505 :     seqoptions = list_copy(seqoptions);
     389                 : 
     390                 :     /*
     391 ECB             :      * Determine namespace and name to use for the sequence.
     392                 :      *
     393                 :      * First, check if a sequence name was passed in as an option.  This is
     394                 :      * used by pg_dump.  Else, generate a name.
     395                 :      *
     396                 :      * Although we use ChooseRelationName, it's not guaranteed that the
     397                 :      * selected sequence name won't conflict; given sufficiently long field
     398                 :      * names, two different serial columns in the same table could be assigned
     399                 :      * the same sequence name, and we'd not notice since we aren't creating
     400                 :      * the sequence quite yet.  In practice this seems quite unlikely to be a
     401                 :      * problem, especially since few people would need two serial columns in
     402                 :      * one table.
     403                 :      */
     404 GIC         616 :     foreach(option, seqoptions)
     405                 :     {
     406             111 :         DefElem    *defel = lfirst_node(DefElem, option);
     407 ECB             : 
     408 GIC         111 :         if (strcmp(defel->defname, "sequence_name") == 0)
     409 ECB             :         {
     410 GIC          14 :             if (nameEl)
     411 LBC           0 :                 errorConflictingDefElem(defel, cxt->pstate);
     412 GIC          14 :             nameEl = defel;
     413 CBC          14 :             nameEl_idx = foreach_current_index(option);
     414 EUB             :         }
     415 ECB             :     }
     416                 : 
     417 GIC         505 :     if (nameEl)
     418                 :     {
     419              14 :         RangeVar   *rv = makeRangeVarFromNameList(castNode(List, nameEl->arg));
     420 ECB             : 
     421 GIC          14 :         snamespace = rv->schemaname;
     422 CBC          14 :         if (!snamespace)
     423                 :         {
     424 ECB             :             /* Given unqualified SEQUENCE NAME, select namespace */
     425 LBC           0 :             if (cxt->rel)
     426 UIC           0 :                 snamespaceid = RelationGetNamespace(cxt->rel);
     427                 :             else
     428 UBC           0 :                 snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
     429               0 :             snamespace = get_namespace_name(snamespaceid);
     430                 :         }
     431 GBC          14 :         sname = rv->relname;
     432 EUB             :         /* Remove the SEQUENCE NAME item from seqoptions */
     433 GIC          14 :         seqoptions = list_delete_nth_cell(seqoptions, nameEl_idx);
     434 ECB             :     }
     435                 :     else
     436                 :     {
     437 GIC         491 :         if (cxt->rel)
     438              71 :             snamespaceid = RelationGetNamespace(cxt->rel);
     439                 :         else
     440 ECB             :         {
     441 CBC         420 :             snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
     442 GIC         420 :             RangeVarAdjustRelationPersistence(cxt->relation, snamespaceid);
     443                 :         }
     444 CBC         491 :         snamespace = get_namespace_name(snamespaceid);
     445             491 :         sname = ChooseRelationName(cxt->relation->relname,
     446 GIC         491 :                                    column->colname,
     447 ECB             :                                    "seq",
     448                 :                                    snamespaceid,
     449                 :                                    false);
     450                 :     }
     451                 : 
     452 GIC         505 :     ereport(DEBUG1,
     453                 :             (errmsg_internal("%s will create implicit sequence \"%s\" for serial column \"%s.%s\"",
     454                 :                              cxt->stmtType, sname,
     455 ECB             :                              cxt->relation->relname, column->colname)));
     456                 : 
     457                 :     /*
     458                 :      * Build a CREATE SEQUENCE command to create the sequence object, and add
     459                 :      * it to the list of things to be done before this CREATE/ALTER TABLE.
     460                 :      */
     461 GIC         505 :     seqstmt = makeNode(CreateSeqStmt);
     462             505 :     seqstmt->for_identity = for_identity;
     463             505 :     seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
     464 CBC         505 :     seqstmt->sequence->relpersistence = cxt->relation->relpersistence;
     465             505 :     seqstmt->options = seqoptions;
     466 ECB             : 
     467                 :     /*
     468                 :      * If a sequence data type was specified, add it to the options.  Prepend
     469                 :      * to the list rather than append; in case a user supplied their own AS
     470                 :      * clause, the "redundant options" error will point to their occurrence,
     471                 :      * not our synthetic one.
     472                 :      */
     473 GIC         505 :     if (seqtypid)
     474             502 :         seqstmt->options = lcons(makeDefElem("as",
     475             502 :                                              (Node *) makeTypeNameFromOid(seqtypid, -1),
     476 ECB             :                                              -1),
     477                 :                                  seqstmt->options);
     478                 : 
     479                 :     /*
     480                 :      * If this is ALTER ADD COLUMN, make sure the sequence will be owned by
     481                 :      * the table's owner.  The current user might be someone else (perhaps a
     482                 :      * superuser, or someone who's only a member of the owning role), but the
     483                 :      * SEQUENCE OWNED BY mechanisms will bleat unless table and sequence have
     484                 :      * exactly the same owning role.
     485                 :      */
     486 GIC         505 :     if (cxt->rel)
     487              85 :         seqstmt->ownerId = cxt->rel->rd_rel->relowner;
     488                 :     else
     489 CBC         420 :         seqstmt->ownerId = InvalidOid;
     490 ECB             : 
     491 GIC         505 :     cxt->blist = lappend(cxt->blist, seqstmt);
     492 ECB             : 
     493                 :     /*
     494                 :      * Store the identity sequence name that we decided on.  ALTER TABLE ...
     495                 :      * ADD COLUMN ... IDENTITY needs this so that it can fill the new column
     496                 :      * with values from the sequence, while the association of the sequence
     497                 :      * with the table is not set until after the ALTER TABLE.
     498                 :      */
     499 GIC         505 :     column->identitySequence = seqstmt->sequence;
     500                 : 
     501                 :     /*
     502 ECB             :      * Build an ALTER SEQUENCE ... OWNED BY command to mark the sequence as
     503                 :      * owned by this column, and add it to the appropriate list of things to
     504                 :      * be done along with this CREATE/ALTER TABLE.  In a CREATE or ALTER ADD
     505                 :      * COLUMN, it must be done after the statement because we don't know the
     506                 :      * column's attnum yet.  But if we do have the attnum (in AT_AddIdentity),
     507                 :      * we can do the marking immediately, which improves some ALTER TABLE
     508                 :      * behaviors.
     509                 :      */
     510 GIC         505 :     altseqstmt = makeNode(AlterSeqStmt);
     511             505 :     altseqstmt->sequence = makeRangeVar(snamespace, sname, -1);
     512             505 :     attnamelist = list_make3(makeString(snamespace),
     513 ECB             :                              makeString(cxt->relation->relname),
     514                 :                              makeString(column->colname));
     515 CBC         505 :     altseqstmt->options = list_make1(makeDefElem("owned_by",
     516                 :                                                  (Node *) attnamelist, -1));
     517 GIC         505 :     altseqstmt->for_identity = for_identity;
     518 ECB             : 
     519 GIC         505 :     if (col_exists)
     520 CBC          51 :         cxt->blist = lappend(cxt->blist, altseqstmt);
     521                 :     else
     522             454 :         cxt->alist = lappend(cxt->alist, altseqstmt);
     523 ECB             : 
     524 GIC         505 :     if (snamespace_p)
     525 CBC         349 :         *snamespace_p = snamespace;
     526 GIC         505 :     if (sname_p)
     527 CBC         349 :         *sname_p = sname;
     528             505 : }
     529 ECB             : 
     530                 : /*
     531                 :  * transformColumnDefinition -
     532                 :  *      transform a single ColumnDef within CREATE TABLE
     533                 :  *      Also used in ALTER TABLE ADD COLUMN
     534                 :  */
     535                 : static void
     536 GIC       34758 : transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
     537                 : {
     538                 :     bool        is_serial;
     539 ECB             :     bool        saw_nullable;
     540                 :     bool        saw_default;
     541                 :     bool        saw_identity;
     542                 :     bool        saw_generated;
     543 GNC       34758 :     bool        need_notnull = false;
     544                 :     ListCell   *clist;
     545                 : 
     546 GIC       34758 :     cxt->columns = lappend(cxt->columns, column);
     547 ECB             : 
     548                 :     /* Check for SERIAL pseudo-types */
     549 GIC       34758 :     is_serial = false;
     550 CBC       34758 :     if (column->typeName
     551 GIC       34615 :         && list_length(column->typeName->names) == 1
     552           18152 :         && !column->typeName->pct_type)
     553 ECB             :     {
     554 CBC       18152 :         char       *typname = strVal(linitial(column->typeName->names));
     555 ECB             : 
     556 CBC       18152 :         if (strcmp(typname, "smallserial") == 0 ||
     557 GIC       18148 :             strcmp(typname, "serial2") == 0)
     558 ECB             :         {
     559 GIC           7 :             is_serial = true;
     560 CBC           7 :             column->typeName->names = NIL;
     561               7 :             column->typeName->typeOid = INT2OID;
     562                 :         }
     563           18145 :         else if (strcmp(typname, "serial") == 0 ||
     564           17813 :                  strcmp(typname, "serial4") == 0)
     565 ECB             :         {
     566 GIC         332 :             is_serial = true;
     567 CBC         332 :             column->typeName->names = NIL;
     568             332 :             column->typeName->typeOid = INT4OID;
     569                 :         }
     570           17813 :         else if (strcmp(typname, "bigserial") == 0 ||
     571           17809 :                  strcmp(typname, "serial8") == 0)
     572 ECB             :         {
     573 GIC          10 :             is_serial = true;
     574 CBC          10 :             column->typeName->names = NIL;
     575              10 :             column->typeName->typeOid = INT8OID;
     576                 :         }
     577 ECB             : 
     578                 :         /*
     579                 :          * We have to reject "serial[]" explicitly, because once we've set
     580                 :          * typeid, LookupTypeName won't notice arrayBounds.  We don't need any
     581                 :          * special coding for serial(typmod) though.
     582                 :          */
     583 GIC       18152 :         if (is_serial && column->typeName->arrayBounds != NIL)
     584 UIC           0 :             ereport(ERROR,
     585                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     586                 :                      errmsg("array of serial is not implemented"),
     587 ECB             :                      parser_errposition(cxt->pstate,
     588 EUB             :                                         column->typeName->location)));
     589                 :     }
     590                 : 
     591                 :     /* Do necessary work on the column type declaration */
     592 GIC       34758 :     if (column->typeName)
     593           34615 :         transformColumnType(cxt, column);
     594                 : 
     595                 :     /* Special actions for SERIAL pseudo-types */
     596 CBC       34730 :     if (is_serial)
     597 ECB             :     {
     598                 :         char       *snamespace;
     599                 :         char       *sname;
     600                 :         char       *qstring;
     601                 :         A_Const    *snamenode;
     602                 :         TypeCast   *castnode;
     603                 :         FuncCall   *funccallnode;
     604                 :         Constraint *constraint;
     605                 : 
     606 GIC         349 :         generateSerialExtraStmts(cxt, column,
     607             349 :                                  column->typeName->typeOid, NIL,
     608                 :                                  false, false,
     609                 :                                  &snamespace, &sname);
     610 ECB             : 
     611                 :         /*
     612                 :          * Create appropriate constraints for SERIAL.  We do this in full,
     613                 :          * rather than shortcutting, so that we will detect any conflicting
     614                 :          * constraints the user wrote (like a different DEFAULT).
     615                 :          *
     616                 :          * Create an expression tree representing the function call
     617                 :          * nextval('sequencename').  We cannot reduce the raw tree to cooked
     618                 :          * form until after the sequence is created, but there's no need to do
     619                 :          * so.
     620                 :          */
     621 GIC         349 :         qstring = quote_qualified_identifier(snamespace, sname);
     622             349 :         snamenode = makeNode(A_Const);
     623             349 :         snamenode->val.node.type = T_String;
     624             349 :         snamenode->val.sval.sval = qstring;
     625 CBC         349 :         snamenode->location = -1;
     626             349 :         castnode = makeNode(TypeCast);
     627             349 :         castnode->typeName = SystemTypeName("regclass");
     628             349 :         castnode->arg = (Node *) snamenode;
     629             349 :         castnode->location = -1;
     630             349 :         funccallnode = makeFuncCall(SystemFuncName("nextval"),
     631             349 :                                     list_make1(castnode),
     632 ECB             :                                     COERCE_EXPLICIT_CALL,
     633                 :                                     -1);
     634 CBC         349 :         constraint = makeNode(Constraint);
     635             349 :         constraint->contype = CONSTR_DEFAULT;
     636 GIC         349 :         constraint->location = -1;
     637             349 :         constraint->raw_expr = (Node *) funccallnode;
     638 CBC         349 :         constraint->cooked_expr = NULL;
     639             349 :         column->constraints = lappend(column->constraints, constraint);
     640 ECB             : 
     641                 :         /* have a NOT NULL constraint added later */
     642 GNC         349 :         need_notnull = true;
     643                 :     }
     644 ECB             : 
     645                 :     /* Process column constraints, if any... */
     646 GIC       34730 :     transformConstraintAttrs(cxt, column->constraints);
     647                 : 
     648 CBC       34730 :     saw_nullable = false;
     649 GIC       34730 :     saw_default = false;
     650 CBC       34730 :     saw_identity = false;
     651           34730 :     saw_generated = false;
     652 ECB             : 
     653 CBC       42268 :     foreach(clist, column->constraints)
     654                 :     {
     655            7580 :         Constraint *constraint = lfirst_node(Constraint, clist);
     656                 : 
     657            7580 :         switch (constraint->contype)
     658                 :         {
     659              11 :             case CONSTR_NULL:
     660 GNC          11 :                 if ((saw_nullable && column->is_not_null) || need_notnull)
     661 CBC           3 :                     ereport(ERROR,
     662 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
     663                 :                              errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
     664                 :                                     column->colname, cxt->relation->relname),
     665                 :                              parser_errposition(cxt->pstate,
     666                 :                                                 constraint->location)));
     667 GIC           8 :                 column->is_not_null = false;
     668               8 :                 saw_nullable = true;
     669 CBC           8 :                 break;
     670 ECB             : 
     671 CBC        2686 :             case CONSTR_NOTNULL:
     672                 : 
     673                 :                 /*
     674                 :                  * For NOT NULL declarations, we need to mark the column as
     675                 :                  * not nullable, and set things up to have a CHECK constraint
     676                 :                  * created.  Also, duplicate NOT NULL declarations are not
     677                 :                  * allowed.
     678                 :                  */
     679 GNC        2686 :                 if (saw_nullable)
     680                 :                 {
     681 UNC           0 :                     if (!column->is_not_null)
     682               0 :                         ereport(ERROR,
     683                 :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     684                 :                                  errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
     685                 :                                         column->colname, cxt->relation->relname),
     686                 :                                  parser_errposition(cxt->pstate,
     687                 :                                                     constraint->location)));
     688                 :                     else
     689               0 :                         ereport(ERROR,
     690                 :                                 errcode(ERRCODE_SYNTAX_ERROR),
     691                 :                                 errmsg("redundant NOT NULL declarations for column \"%s\" of table \"%s\"",
     692                 :                                        column->colname, cxt->relation->relname),
     693                 :                                 parser_errposition(cxt->pstate,
     694                 :                                                    constraint->location));
     695                 :                 }
     696                 : 
     697                 :                 /*
     698                 :                  * If this is the first time we see this column being marked
     699                 :                  * not null, keep track to later add a NOT NULL constraint.
     700                 :                  */
     701 GNC        2686 :                 if (!column->is_not_null)
     702                 :                 {
     703                 :                     Constraint *notnull;
     704                 : 
     705            2686 :                     column->is_not_null = true;
     706            2686 :                     saw_nullable = true;
     707                 : 
     708            2686 :                     notnull = makeNode(Constraint);
     709            2686 :                     notnull->contype = CONSTR_NOTNULL;
     710            2686 :                     notnull->conname = constraint->conname;
     711            2686 :                     notnull->deferrable = false;
     712            2686 :                     notnull->initdeferred = false;
     713            2686 :                     notnull->location = -1;
     714            2686 :                     notnull->colname = column->colname;
     715            2686 :                     notnull->skip_validation = false;
     716            2686 :                     notnull->initially_valid = true;
     717                 : 
     718            2686 :                     cxt->nnconstraints = lappend(cxt->nnconstraints, notnull);
     719                 : 
     720                 :                     /* Don't need this anymore, if we had it */
     721            2686 :                     need_notnull = false;
     722                 :                 }
     723                 : 
     724 CBC        2686 :                 break;
     725                 : 
     726 GBC        1074 :             case CONSTR_DEFAULT:
     727            1074 :                 if (saw_default)
     728 UIC           0 :                     ereport(ERROR,
     729                 :                             (errcode(ERRCODE_SYNTAX_ERROR),
     730                 :                              errmsg("multiple default values specified for column \"%s\" of table \"%s\"",
     731                 :                                     column->colname, cxt->relation->relname),
     732                 :                              parser_errposition(cxt->pstate,
     733                 :                                                 constraint->location)));
     734 GBC        1074 :                 column->raw_default = constraint->raw_expr;
     735 GIC        1074 :                 Assert(constraint->cooked_expr == NULL);
     736            1074 :                 saw_default = true;
     737            1074 :                 break;
     738                 : 
     739             114 :             case CONSTR_IDENTITY:
     740                 :                 {
     741                 :                     Type        ctype;
     742                 :                     Oid         typeOid;
     743                 : 
     744             114 :                     if (cxt->ofType)
     745               3 :                         ereport(ERROR,
     746 ECB             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     747                 :                                  errmsg("identity columns are not supported on typed tables")));
     748 GIC         111 :                     if (cxt->partbound)
     749               6 :                         ereport(ERROR,
     750 ECB             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     751                 :                                  errmsg("identity columns are not supported on partitions")));
     752                 : 
     753 CBC         105 :                     ctype = typenameType(cxt->pstate, column->typeName, NULL);
     754             105 :                     typeOid = ((Form_pg_type) GETSTRUCT(ctype))->oid;
     755             105 :                     ReleaseSysCache(ctype);
     756 ECB             : 
     757 CBC         105 :                     if (saw_identity)
     758               3 :                         ereport(ERROR,
     759 ECB             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     760                 :                                  errmsg("multiple identity specifications for column \"%s\" of table \"%s\"",
     761                 :                                         column->colname, cxt->relation->relname),
     762                 :                                  parser_errposition(cxt->pstate,
     763                 :                                                     constraint->location)));
     764                 : 
     765 GIC         102 :                     generateSerialExtraStmts(cxt, column,
     766 ECB             :                                              typeOid, constraint->options,
     767                 :                                              true, false,
     768                 :                                              NULL, NULL);
     769                 : 
     770 GIC         102 :                     column->identity = constraint->generated_when;
     771 CBC         102 :                     saw_identity = true;
     772 ECB             : 
     773                 :                     /*
     774                 :                      * Identity columns are always NOT NULL, but we may have a
     775                 :                      * constraint already.
     776                 :                      */
     777 GNC         102 :                     if (!saw_nullable)
     778              90 :                         need_notnull = true;
     779              12 :                     else if (!column->is_not_null)
     780 GIC           3 :                         ereport(ERROR,
     781                 :                                 (errcode(ERRCODE_SYNTAX_ERROR),
     782                 :                                  errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
     783                 :                                         column->colname, cxt->relation->relname),
     784 ECB             :                                  parser_errposition(cxt->pstate,
     785                 :                                                     constraint->location)));
     786 GIC          99 :                     break;
     787 ECB             :                 }
     788                 : 
     789 GIC         412 :             case CONSTR_GENERATED:
     790             412 :                 if (cxt->ofType)
     791               3 :                     ereport(ERROR,
     792 ECB             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     793                 :                              errmsg("generated columns are not supported on typed tables")));
     794 GIC         409 :                 if (saw_generated)
     795               3 :                     ereport(ERROR,
     796 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
     797                 :                              errmsg("multiple generation clauses specified for column \"%s\" of table \"%s\"",
     798                 :                                     column->colname, cxt->relation->relname),
     799                 :                              parser_errposition(cxt->pstate,
     800                 :                                                 constraint->location)));
     801 CBC         406 :                 column->generated = ATTRIBUTE_GENERATED_STORED;
     802 GIC         406 :                 column->raw_default = constraint->raw_expr;
     803             406 :                 Assert(constraint->cooked_expr == NULL);
     804             406 :                 saw_generated = true;
     805             406 :                 break;
     806                 : 
     807             160 :             case CONSTR_CHECK:
     808 CBC         160 :                 cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
     809                 : 
     810                 :                 /*
     811                 :                  * XXX If the user says CHECK (IS NOT NULL), should we turn
     812                 :                  * that into a regular NOT NULL constraint?
     813                 :                  */
     814 GIC         160 :                 break;
     815                 : 
     816            2545 :             case CONSTR_PRIMARY:
     817            2545 :                 if (cxt->isforeign)
     818 CBC           3 :                     ereport(ERROR,
     819 ECB             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     820                 :                              errmsg("primary key constraints are not supported on foreign tables"),
     821                 :                              parser_errposition(cxt->pstate,
     822                 :                                                 constraint->location)));
     823                 :                 /* FALL THRU */
     824                 : 
     825                 :             case CONSTR_UNIQUE:
     826 CBC        2688 :                 if (cxt->isforeign)
     827 LBC           0 :                     ereport(ERROR,
     828 ECB             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     829                 :                              errmsg("unique constraints are not supported on foreign tables"),
     830                 :                              parser_errposition(cxt->pstate,
     831                 :                                                 constraint->location)));
     832 GIC        2688 :                 if (constraint->keys == NIL)
     833            2688 :                     constraint->keys = list_make1(makeString(column->colname));
     834 CBC        2688 :                 cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
     835 GIC        2688 :                 break;
     836                 : 
     837 LBC           0 :             case CONSTR_EXCLUSION:
     838 ECB             :                 /* grammar does not allow EXCLUDE as a column constraint */
     839 LBC           0 :                 elog(ERROR, "column exclusion constraints are not supported");
     840                 :                 break;
     841                 : 
     842 CBC         358 :             case CONSTR_FOREIGN:
     843             358 :                 if (cxt->isforeign)
     844 GIC           3 :                     ereport(ERROR,
     845                 :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     846                 :                              errmsg("foreign key constraints are not supported on foreign tables"),
     847                 :                              parser_errposition(cxt->pstate,
     848                 :                                                 constraint->location)));
     849 ECB             : 
     850                 :                 /*
     851                 :                  * Fill in the current attribute's name and throw it into the
     852                 :                  * list of FK constraints to be processed later.
     853                 :                  */
     854 GIC         355 :                 constraint->fk_attrs = list_make1(makeString(column->colname));
     855 CBC         355 :                 cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
     856             355 :                 break;
     857                 : 
     858 GIC          74 :             case CONSTR_ATTR_DEFERRABLE:
     859                 :             case CONSTR_ATTR_NOT_DEFERRABLE:
     860                 :             case CONSTR_ATTR_DEFERRED:
     861                 :             case CONSTR_ATTR_IMMEDIATE:
     862 ECB             :                 /* transformConstraintAttrs took care of these */
     863 GIC          74 :                 break;
     864 ECB             : 
     865 LBC           0 :             default:
     866               0 :                 elog(ERROR, "unrecognized constraint type: %d",
     867                 :                      constraint->contype);
     868                 :                 break;
     869                 :         }
     870                 : 
     871 GIC        7550 :         if (saw_default && saw_identity)
     872               6 :             ereport(ERROR,
     873                 :                     (errcode(ERRCODE_SYNTAX_ERROR),
     874 ECB             :                      errmsg("both default and identity specified for column \"%s\" of table \"%s\"",
     875 EUB             :                             column->colname, cxt->relation->relname),
     876                 :                      parser_errposition(cxt->pstate,
     877                 :                                         constraint->location)));
     878                 : 
     879 GIC        7544 :         if (saw_default && saw_generated)
     880 CBC           3 :             ereport(ERROR,
     881 ECB             :                     (errcode(ERRCODE_SYNTAX_ERROR),
     882                 :                      errmsg("both default and generation expression specified for column \"%s\" of table \"%s\"",
     883                 :                             column->colname, cxt->relation->relname),
     884                 :                      parser_errposition(cxt->pstate,
     885 EUB             :                                         constraint->location)));
     886                 : 
     887 GBC        7541 :         if (saw_identity && saw_generated)
     888 GIC           3 :             ereport(ERROR,
     889                 :                     (errcode(ERRCODE_SYNTAX_ERROR),
     890 ECB             :                      errmsg("both identity and generation expression specified for column \"%s\" of table \"%s\"",
     891                 :                             column->colname, cxt->relation->relname),
     892                 :                      parser_errposition(cxt->pstate,
     893                 :                                         constraint->location)));
     894                 :     }
     895                 : 
     896                 :     /*
     897                 :      * If we need a NOT NULL constraint for SERIAL or IDENTITY, and one was
     898                 :      * not explicitly specified, add one now.
     899                 :      */
     900 GNC       34688 :     if (need_notnull && !(saw_nullable && column->is_not_null))
     901                 :     {
     902                 :         Constraint *notnull;
     903                 : 
     904             385 :         column->is_not_null = true;
     905                 : 
     906             385 :         notnull = makeNode(Constraint);
     907             385 :         notnull->contype = CONSTR_NOTNULL;
     908             385 :         notnull->conname = NULL;
     909             385 :         notnull->deferrable = false;
     910             385 :         notnull->initdeferred = false;
     911             385 :         notnull->location = -1;
     912             385 :         notnull->colname = column->colname;
     913             385 :         notnull->skip_validation = false;
     914             385 :         notnull->initially_valid = true;
     915                 : 
     916             385 :         cxt->nnconstraints = lappend(cxt->nnconstraints, notnull);
     917                 :     }
     918                 : 
     919                 :     /*
     920                 :      * If needed, generate ALTER FOREIGN TABLE ALTER COLUMN statement to add
     921                 :      * per-column foreign data wrapper options to this column after creation.
     922                 :      */
     923 GIC       34688 :     if (column->fdwoptions != NIL)
     924                 :     {
     925 ECB             :         AlterTableStmt *stmt;
     926                 :         AlterTableCmd *cmd;
     927                 : 
     928 GIC          76 :         cmd = makeNode(AlterTableCmd);
     929 CBC          76 :         cmd->subtype = AT_AlterColumnGenericOptions;
     930 GIC          76 :         cmd->name = column->colname;
     931              76 :         cmd->def = (Node *) column->fdwoptions;
     932              76 :         cmd->behavior = DROP_RESTRICT;
     933              76 :         cmd->missing_ok = false;
     934 ECB             : 
     935 GIC          76 :         stmt = makeNode(AlterTableStmt);
     936 GBC          76 :         stmt->relation = cxt->relation;
     937              76 :         stmt->cmds = NIL;
     938 GIC          76 :         stmt->objtype = OBJECT_FOREIGN_TABLE;
     939              76 :         stmt->cmds = lappend(stmt->cmds, cmd);
     940                 : 
     941              76 :         cxt->alist = lappend(cxt->alist, stmt);
     942 ECB             :     }
     943 CBC       34688 : }
     944                 : 
     945                 : /*
     946                 :  * transformTableConstraint
     947                 :  *      transform a Constraint node within CREATE TABLE or ALTER TABLE
     948                 :  */
     949                 : static void
     950           36310 : transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
     951 ECB             : {
     952 GIC       36310 :     switch (constraint->contype)
     953                 :     {
     954           19546 :         case CONSTR_PRIMARY:
     955           19546 :             if (cxt->isforeign)
     956               3 :                 ereport(ERROR,
     957                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     958 ECB             :                          errmsg("primary key constraints are not supported on foreign tables"),
     959                 :                          parser_errposition(cxt->pstate,
     960                 :                                             constraint->location)));
     961 GIC       19543 :             cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
     962           19543 :             break;
     963                 : 
     964           14774 :         case CONSTR_UNIQUE:
     965           14774 :             if (cxt->isforeign)
     966               3 :                 ereport(ERROR,
     967                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     968                 :                          errmsg("unique constraints are not supported on foreign tables"),
     969                 :                          parser_errposition(cxt->pstate,
     970                 :                                             constraint->location)));
     971 CBC       14771 :             cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
     972 GIC       14771 :             break;
     973                 : 
     974              76 :         case CONSTR_EXCLUSION:
     975 CBC          76 :             if (cxt->isforeign)
     976 UIC           0 :                 ereport(ERROR,
     977 ECB             :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     978                 :                          errmsg("exclusion constraints are not supported on foreign tables"),
     979                 :                          parser_errposition(cxt->pstate,
     980                 :                                             constraint->location)));
     981 CBC          76 :             if (cxt->ispartitioned)
     982              12 :                 ereport(ERROR,
     983 ECB             :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     984                 :                          errmsg("exclusion constraints are not supported on partitioned tables"),
     985                 :                          parser_errposition(cxt->pstate,
     986                 :                                             constraint->location)));
     987 CBC          64 :             cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
     988 GIC          64 :             break;
     989                 : 
     990             552 :         case CONSTR_CHECK:
     991             552 :             cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
     992             552 :             break;
     993                 : 
     994 GNC         117 :         case CONSTR_NOTNULL:
     995             117 :             cxt->nnconstraints = lappend(cxt->nnconstraints, constraint);
     996             117 :             break;
     997                 : 
     998 CBC        1245 :         case CONSTR_FOREIGN:
     999 GIC        1245 :             if (cxt->isforeign)
    1000 UIC           0 :                 ereport(ERROR,
    1001                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1002                 :                          errmsg("foreign key constraints are not supported on foreign tables"),
    1003 ECB             :                          parser_errposition(cxt->pstate,
    1004                 :                                             constraint->location)));
    1005 CBC        1245 :             cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
    1006            1245 :             break;
    1007 ECB             : 
    1008 LBC           0 :         case CONSTR_NULL:
    1009 ECB             :         case CONSTR_DEFAULT:
    1010                 :         case CONSTR_ATTR_DEFERRABLE:
    1011                 :         case CONSTR_ATTR_NOT_DEFERRABLE:
    1012                 :         case CONSTR_ATTR_DEFERRED:
    1013                 :         case CONSTR_ATTR_IMMEDIATE:
    1014 UIC           0 :             elog(ERROR, "invalid context for constraint type %d",
    1015 ECB             :                  constraint->contype);
    1016                 :             break;
    1017                 : 
    1018 UIC           0 :         default:
    1019               0 :             elog(ERROR, "unrecognized constraint type: %d",
    1020                 :                  constraint->contype);
    1021                 :             break;
    1022                 :     }
    1023 GIC       36292 : }
    1024 ECB             : 
    1025                 : /*
    1026                 :  * transformTableLikeClause
    1027                 :  *
    1028                 :  * Change the LIKE <srctable> portion of a CREATE TABLE statement into
    1029                 :  * column definitions that recreate the user defined column portions of
    1030                 :  * <srctable>.  Also, if there are any LIKE options that we can't fully
    1031                 :  * process at this point, add the TableLikeClause to cxt->likeclauses, which
    1032                 :  * will cause utility.c to call expandTableLikeClause() after the new
    1033                 :  * table has been created.
    1034                 :  */
    1035                 : static void
    1036 CBC         348 : transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause)
    1037                 : {
    1038 ECB             :     AttrNumber  parent_attno;
    1039                 :     Relation    relation;
    1040                 :     TupleDesc   tupleDesc;
    1041                 :     AclResult   aclresult;
    1042                 :     char       *comment;
    1043                 :     ParseCallbackState pcbstate;
    1044                 :     bool        process_notnull_constraints;
    1045                 : 
    1046 CBC         348 :     setup_parser_errposition_callback(&pcbstate, cxt->pstate,
    1047             348 :                                       table_like_clause->relation->location);
    1048                 : 
    1049 ECB             :     /* we could support LIKE in many cases, but worry about it another day */
    1050 CBC         348 :     if (cxt->isforeign)
    1051 UBC           0 :         ereport(ERROR,
    1052                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1053                 :                  errmsg("LIKE is not supported for creating foreign tables")));
    1054                 : 
    1055                 :     /* Open the relation referenced by the LIKE clause */
    1056 CBC         348 :     relation = relation_openrv(table_like_clause->relation, AccessShareLock);
    1057 ECB             : 
    1058 GIC         345 :     if (relation->rd_rel->relkind != RELKIND_RELATION &&
    1059             193 :         relation->rd_rel->relkind != RELKIND_VIEW &&
    1060             187 :         relation->rd_rel->relkind != RELKIND_MATVIEW &&
    1061             187 :         relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
    1062 CBC         184 :         relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
    1063             184 :         relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
    1064 GIC           3 :         ereport(ERROR,
    1065 ECB             :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1066                 :                  errmsg("relation \"%s\" is invalid in LIKE clause",
    1067                 :                         RelationGetRelationName(relation)),
    1068                 :                  errdetail_relkind_not_supported(relation->rd_rel->relkind)));
    1069                 : 
    1070 CBC         342 :     cancel_parser_errposition_callback(&pcbstate);
    1071 ECB             : 
    1072                 :     /*
    1073                 :      * Check for privileges
    1074                 :      */
    1075 GBC         342 :     if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
    1076                 :     {
    1077 GNC           3 :         aclresult = object_aclcheck(TypeRelationId, relation->rd_rel->reltype, GetUserId(),
    1078                 :                                      ACL_USAGE);
    1079 GIC           3 :         if (aclresult != ACLCHECK_OK)
    1080 LBC           0 :             aclcheck_error(aclresult, OBJECT_TYPE,
    1081               0 :                            RelationGetRelationName(relation));
    1082                 :     }
    1083 EUB             :     else
    1084                 :     {
    1085 GIC         339 :         aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
    1086                 :                                       ACL_SELECT);
    1087             339 :         if (aclresult != ACLCHECK_OK)
    1088 UIC           0 :             aclcheck_error(aclresult, get_relkind_objtype(relation->rd_rel->relkind),
    1089 UBC           0 :                            RelationGetRelationName(relation));
    1090                 :     }
    1091                 : 
    1092 GIC         342 :     tupleDesc = RelationGetDescr(relation);
    1093 EUB             : 
    1094                 :     /*
    1095                 :      * Insert the copied attributes into the cxt for the new table definition.
    1096                 :      * We must do this now so that they appear in the table in the relative
    1097                 :      * position where the LIKE clause is, as required by SQL99.
    1098 ECB             :      */
    1099 GIC        1066 :     for (parent_attno = 1; parent_attno <= tupleDesc->natts;
    1100             724 :          parent_attno++)
    1101                 :     {
    1102             724 :         Form_pg_attribute attribute = TupleDescAttr(tupleDesc,
    1103                 :                                                     parent_attno - 1);
    1104             724 :         char       *attributeName = NameStr(attribute->attname);
    1105                 :         ColumnDef  *def;
    1106                 : 
    1107                 :         /*
    1108                 :          * Ignore dropped columns in the parent.
    1109                 :          */
    1110             724 :         if (attribute->attisdropped)
    1111 CBC           6 :             continue;
    1112                 : 
    1113                 :         /*
    1114                 :          * Create a new column, which is marked as NOT inherited.
    1115                 :          *
    1116                 :          * For constraints, ONLY the NOT NULL constraint is inherited by the
    1117                 :          * new column definition per SQL99.
    1118                 :          */
    1119 GIC         718 :         def = makeNode(ColumnDef);
    1120             718 :         def->colname = pstrdup(attributeName);
    1121 CBC         718 :         def->typeName = makeTypeNameFromOid(attribute->atttypid,
    1122 ECB             :                                             attribute->atttypmod);
    1123 GIC         718 :         def->inhcount = 0;
    1124             718 :         def->is_local = true;
    1125 CBC         718 :         def->is_not_null = attribute->attnotnull;
    1126 GNC         718 :         if (attribute->attnotnull)
    1127             139 :             process_notnull_constraints = true;
    1128 GBC         718 :         def->is_from_type = false;
    1129 GIC         718 :         def->storage = 0;
    1130             718 :         def->raw_default = NULL;
    1131             718 :         def->cooked_default = NULL;
    1132             718 :         def->collClause = NULL;
    1133 CBC         718 :         def->collOid = attribute->attcollation;
    1134 GIC         718 :         def->constraints = NIL;
    1135 CBC         718 :         def->location = -1;
    1136 ECB             : 
    1137                 :         /*
    1138                 :          * Add to column list
    1139                 :          */
    1140 CBC         718 :         cxt->columns = lappend(cxt->columns, def);
    1141 ECB             : 
    1142                 :         /*
    1143                 :          * Although we don't transfer the column's default/generation
    1144                 :          * expression now, we need to mark it GENERATED if appropriate.
    1145                 :          */
    1146 GIC         718 :         if (attribute->atthasdef && attribute->attgenerated &&
    1147 CBC          24 :             (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED))
    1148 GIC          15 :             def->generated = attribute->attgenerated;
    1149                 : 
    1150                 :         /*
    1151                 :          * Copy identity if requested
    1152 ECB             :          */
    1153 GIC         718 :         if (attribute->attidentity &&
    1154 CBC           6 :             (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY))
    1155                 :         {
    1156 ECB             :             Oid         seq_relid;
    1157 EUB             :             List       *seq_options;
    1158                 : 
    1159                 :             /*
    1160                 :              * find sequence owned by old column; extract sequence parameters;
    1161                 :              * build new create sequence command
    1162 ECB             :              */
    1163 GIC           3 :             seq_relid = getIdentitySequence(RelationGetRelid(relation), attribute->attnum, false);
    1164 CBC           3 :             seq_options = sequence_options(seq_relid);
    1165 GBC           3 :             generateSerialExtraStmts(cxt, def,
    1166 EUB             :                                      InvalidOid, seq_options,
    1167                 :                                      true, false,
    1168                 :                                      NULL, NULL);
    1169 CBC           3 :             def->identity = attribute->attidentity;
    1170                 :         }
    1171                 : 
    1172                 :         /* Likewise, copy storage if requested */
    1173 GIC         718 :         if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
    1174              66 :             def->storage = attribute->attstorage;
    1175                 :         else
    1176 CBC         652 :             def->storage = 0;
    1177 ECB             : 
    1178                 :         /* Likewise, copy compression if requested */
    1179 CBC         718 :         if ((table_like_clause->options & CREATE_TABLE_LIKE_COMPRESSION) != 0
    1180 GIC          42 :             && CompressionMethodIsValid(attribute->attcompression))
    1181 CBC           3 :             def->compression =
    1182 GIC           3 :                 pstrdup(GetCompressionMethodName(attribute->attcompression));
    1183                 :         else
    1184             715 :             def->compression = NULL;
    1185                 : 
    1186                 :         /* Likewise, copy comment if requested */
    1187 CBC         778 :         if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
    1188              60 :             (comment = GetComment(attribute->attrelid,
    1189                 :                                   RelationRelationId,
    1190 GIC          60 :                                   attribute->attnum)) != NULL)
    1191                 :         {
    1192              39 :             CommentStmt *stmt = makeNode(CommentStmt);
    1193                 : 
    1194              39 :             stmt->objtype = OBJECT_COLUMN;
    1195              39 :             stmt->object = (Node *) list_make3(makeString(cxt->relation->schemaname),
    1196 ECB             :                                                makeString(cxt->relation->relname),
    1197                 :                                                makeString(def->colname));
    1198 CBC          39 :             stmt->comment = comment;
    1199                 : 
    1200              39 :             cxt->alist = lappend(cxt->alist, stmt);
    1201 ECB             :         }
    1202                 :     }
    1203                 : 
    1204                 :     /*
    1205                 :      * We cannot yet deal with defaults, CHECK constraints, or indexes, since
    1206                 :      * we don't yet know what column numbers the copied columns will have in
    1207                 :      * the finished table.  If any of those options are specified, add the
    1208                 :      * LIKE clause to cxt->likeclauses so that expandTableLikeClause will be
    1209                 :      * called after we do know that; in addition, do that if there are any NOT
    1210                 :      * NULL constraints, because those must be propagated even if not
    1211                 :      * explicitly requested.
    1212                 :      *
    1213                 :      * In order for this to work, we remember the relation OID so that
    1214                 :      * expandTableLikeClause is certain to open the same table.
    1215                 :      */
    1216 GNC         342 :     if ((table_like_clause->options &
    1217                 :         (CREATE_TABLE_LIKE_DEFAULTS |
    1218                 :          CREATE_TABLE_LIKE_GENERATED |
    1219                 :          CREATE_TABLE_LIKE_CONSTRAINTS |
    1220             263 :          CREATE_TABLE_LIKE_INDEXES)) ||
    1221                 :         process_notnull_constraints)
    1222 ECB             :     {
    1223 GIC         322 :         table_like_clause->relationOid = RelationGetRelid(relation);
    1224             322 :         cxt->likeclauses = lappend(cxt->likeclauses, table_like_clause);
    1225                 :     }
    1226                 : 
    1227                 :     /*
    1228 ECB             :      * We may copy extended statistics if requested, since the representation
    1229                 :      * of CreateStatsStmt doesn't depend on column numbers.
    1230                 :      */
    1231 GIC         342 :     if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
    1232                 :     {
    1233                 :         List       *parent_extstats;
    1234                 :         ListCell   *l;
    1235 ECB             : 
    1236 CBC          21 :         parent_extstats = RelationGetStatExtList(relation);
    1237                 : 
    1238 GIC          39 :         foreach(l, parent_extstats)
    1239                 :         {
    1240              18 :             Oid         parent_stat_oid = lfirst_oid(l);
    1241                 :             CreateStatsStmt *stats_stmt;
    1242                 : 
    1243              18 :             stats_stmt = generateClonedExtStatsStmt(cxt->relation,
    1244                 :                                                     RelationGetRelid(relation),
    1245 ECB             :                                                     parent_stat_oid);
    1246                 : 
    1247                 :             /* Copy comment on statistics object, if requested */
    1248 GIC          18 :             if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
    1249                 :             {
    1250              18 :                 comment = GetComment(parent_stat_oid, StatisticExtRelationId, 0);
    1251 ECB             : 
    1252                 :                 /*
    1253                 :                  * We make use of CreateStatsStmt's stxcomment option, so as
    1254                 :                  * not to need to know now what name the statistics will have.
    1255                 :                  */
    1256 CBC          18 :                 stats_stmt->stxcomment = comment;
    1257                 :             }
    1258 ECB             : 
    1259 GIC          18 :             cxt->extstats = lappend(cxt->extstats, stats_stmt);
    1260                 :         }
    1261 ECB             : 
    1262 CBC          21 :         list_free(parent_extstats);
    1263 ECB             :     }
    1264                 : 
    1265                 :     /*
    1266                 :      * Close the parent rel, but keep our AccessShareLock on it until xact
    1267                 :      * commit.  That will prevent someone else from deleting or ALTERing the
    1268                 :      * parent before we can run expandTableLikeClause.
    1269                 :      */
    1270 CBC         342 :     table_close(relation, NoLock);
    1271 GIC         342 : }
    1272 ECB             : 
    1273                 : /*
    1274                 :  * expandTableLikeClause
    1275                 :  *
    1276                 :  * Process LIKE options that require knowing the final column numbers
    1277                 :  * assigned to the new table's columns.  This executes after we have
    1278                 :  * run DefineRelation for the new table.  It returns a list of utility
    1279                 :  * commands that should be run to generate indexes etc.
    1280                 :  */
    1281                 : List *
    1282 CBC         313 : expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
    1283                 : {
    1284 GIC         313 :     List       *result = NIL;
    1285             313 :     List       *atsubcmds = NIL;
    1286                 :     AttrNumber  parent_attno;
    1287                 :     Relation    relation;
    1288                 :     Relation    childrel;
    1289                 :     TupleDesc   tupleDesc;
    1290                 :     TupleConstr *constr;
    1291                 :     AttrMap    *attmap;
    1292                 :     char       *comment;
    1293                 :     ListCell   *lc;
    1294                 : 
    1295                 :     /*
    1296                 :      * Open the relation referenced by the LIKE clause.  We should still have
    1297                 :      * the table lock obtained by transformTableLikeClause (and this'll throw
    1298                 :      * an assertion failure if not).  Hence, no need to recheck privileges
    1299 ECB             :      * etc.  We must open the rel by OID not name, to be sure we get the same
    1300                 :      * table.
    1301                 :      */
    1302 GIC         313 :     if (!OidIsValid(table_like_clause->relationOid))
    1303 LBC           0 :         elog(ERROR, "expandTableLikeClause called on untransformed LIKE clause");
    1304                 : 
    1305 GIC         313 :     relation = relation_open(table_like_clause->relationOid, NoLock);
    1306 ECB             : 
    1307 CBC         313 :     tupleDesc = RelationGetDescr(relation);
    1308 GIC         313 :     constr = tupleDesc->constr;
    1309                 : 
    1310                 :     /*
    1311                 :      * Open the newly-created child relation; we have lock on that too.
    1312                 :      */
    1313             313 :     childrel = relation_openrv(heapRel, NoLock);
    1314 ECB             : 
    1315                 :     /*
    1316                 :      * Construct a map from the LIKE relation's attnos to the child rel's.
    1317                 :      * This re-checks type match etc, although it shouldn't be possible to
    1318                 :      * have a failure since both tables are locked.
    1319                 :      */
    1320 GIC         313 :     attmap = build_attrmap_by_name(RelationGetDescr(childrel),
    1321                 :                                    tupleDesc,
    1322                 :                                    false);
    1323                 : 
    1324 ECB             :     /*
    1325                 :      * Process defaults, if required.
    1326                 :      */
    1327 CBC         313 :     if ((table_like_clause->options &
    1328 GIC          40 :          (CREATE_TABLE_LIKE_DEFAULTS | CREATE_TABLE_LIKE_GENERATED)) &&
    1329                 :         constr != NULL)
    1330                 :     {
    1331             124 :         for (parent_attno = 1; parent_attno <= tupleDesc->natts;
    1332 CBC          87 :              parent_attno++)
    1333                 :         {
    1334              87 :             Form_pg_attribute attribute = TupleDescAttr(tupleDesc,
    1335                 :                                                         parent_attno - 1);
    1336                 : 
    1337                 :             /*
    1338                 :              * Ignore dropped columns in the parent.
    1339                 :              */
    1340              87 :             if (attribute->attisdropped)
    1341 GIC           3 :                 continue;
    1342                 : 
    1343 ECB             :             /*
    1344                 :              * Copy default, if present and it should be copied.  We have
    1345                 :              * separate options for plain default expressions and GENERATED
    1346                 :              * defaults.
    1347                 :              */
    1348 GIC         118 :             if (attribute->atthasdef &&
    1349              34 :                 (attribute->attgenerated ?
    1350              18 :                  (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED) :
    1351              16 :                  (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)))
    1352                 :             {
    1353              28 :                 Node       *this_default = NULL;
    1354 CBC          28 :                 AttrDefault *attrdef = constr->defval;
    1355 ECB             :                 AlterTableCmd *atsubcmd;
    1356                 :                 bool        found_whole_row;
    1357                 : 
    1358                 :                 /* Find default in constraint structure */
    1359 GIC          37 :                 for (int i = 0; i < constr->num_defval; i++)
    1360                 :                 {
    1361              37 :                     if (attrdef[i].adnum == parent_attno)
    1362                 :                     {
    1363              28 :                         this_default = stringToNode(attrdef[i].adbin);
    1364              28 :                         break;
    1365                 :                     }
    1366 ECB             :                 }
    1367 GIC          28 :                 if (this_default == NULL)
    1368 LBC           0 :                     elog(ERROR, "default expression not found for attribute %d of relation \"%s\"",
    1369 ECB             :                          parent_attno, RelationGetRelationName(relation));
    1370                 : 
    1371 GIC          28 :                 atsubcmd = makeNode(AlterTableCmd);
    1372              28 :                 atsubcmd->subtype = AT_CookedColumnDefault;
    1373              28 :                 atsubcmd->num = attmap->attnums[parent_attno - 1];
    1374              28 :                 atsubcmd->def = map_variable_attnos(this_default,
    1375                 :                                                     1, 0,
    1376                 :                                                     attmap,
    1377                 :                                                     InvalidOid,
    1378                 :                                                     &found_whole_row);
    1379                 : 
    1380                 :                 /*
    1381                 :                  * Prevent this for the same reason as for constraints below.
    1382                 :                  * Note that defaults cannot contain any vars, so it's OK that
    1383                 :                  * the error message refers to generated columns.
    1384                 :                  */
    1385              28 :                 if (found_whole_row)
    1386 LBC           0 :                     ereport(ERROR,
    1387 EUB             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1388                 :                              errmsg("cannot convert whole-row table reference"),
    1389 ECB             :                              errdetail("Generation expression for column \"%s\" contains a whole-row reference to table \"%s\".",
    1390                 :                                        NameStr(attribute->attname),
    1391                 :                                        RelationGetRelationName(relation))));
    1392                 : 
    1393 GIC          28 :                 atsubcmds = lappend(atsubcmds, atsubcmd);
    1394                 :             }
    1395                 :         }
    1396                 :     }
    1397 ECB             : 
    1398                 :     /*
    1399                 :      * Copy CHECK constraints if requested, being careful to adjust attribute
    1400                 :      * numbers so they match the child.
    1401                 :      */
    1402 GIC         313 :     if ((table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS) &&
    1403                 :         constr != NULL)
    1404 ECB             :     {
    1405                 :         int         ccnum;
    1406                 : 
    1407 GIC          93 :         for (ccnum = 0; ccnum < constr->num_check; ccnum++)
    1408                 :         {
    1409              48 :             char       *ccname = constr->check[ccnum].ccname;
    1410              48 :             char       *ccbin = constr->check[ccnum].ccbin;
    1411 CBC          48 :             bool        ccnoinherit = constr->check[ccnum].ccnoinherit;
    1412 ECB             :             Node       *ccbin_node;
    1413                 :             bool        found_whole_row;
    1414                 :             Constraint *n;
    1415                 :             AlterTableCmd *atsubcmd;
    1416                 : 
    1417 GIC          48 :             ccbin_node = map_variable_attnos(stringToNode(ccbin),
    1418 ECB             :                                              1, 0,
    1419                 :                                              attmap,
    1420                 :                                              InvalidOid, &found_whole_row);
    1421                 : 
    1422                 :             /*
    1423                 :              * We reject whole-row variables because the whole point of LIKE
    1424                 :              * is that the new table's rowtype might later diverge from the
    1425                 :              * parent's.  So, while translation might be possible right now,
    1426                 :              * it wouldn't be possible to guarantee it would work in future.
    1427                 :              */
    1428 GIC          48 :             if (found_whole_row)
    1429 UIC           0 :                 ereport(ERROR,
    1430                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1431                 :                          errmsg("cannot convert whole-row table reference"),
    1432 ECB             :                          errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
    1433                 :                                    ccname,
    1434                 :                                    RelationGetRelationName(relation))));
    1435                 : 
    1436 GIC          48 :             n = makeNode(Constraint);
    1437 CBC          48 :             n->contype = CONSTR_CHECK;
    1438              48 :             n->conname = pstrdup(ccname);
    1439 GIC          48 :             n->location = -1;
    1440              48 :             n->is_no_inherit = ccnoinherit;
    1441              48 :             n->raw_expr = NULL;
    1442              48 :             n->cooked_expr = nodeToString(ccbin_node);
    1443 ECB             : 
    1444                 :             /* We can skip validation, since the new table should be empty. */
    1445 CBC          48 :             n->skip_validation = true;
    1446 GIC          48 :             n->initially_valid = true;
    1447 ECB             : 
    1448 CBC          48 :             atsubcmd = makeNode(AlterTableCmd);
    1449 GIC          48 :             atsubcmd->subtype = AT_AddConstraint;
    1450              48 :             atsubcmd->def = (Node *) n;
    1451 CBC          48 :             atsubcmds = lappend(atsubcmds, atsubcmd);
    1452 EUB             : 
    1453                 :             /* Copy comment on constraint */
    1454 GIC          75 :             if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
    1455 CBC          27 :                 (comment = GetComment(get_relation_constraint_oid(RelationGetRelid(relation),
    1456              27 :                                                                   n->conname, false),
    1457 ECB             :                                       ConstraintRelationId,
    1458                 :                                       0)) != NULL)
    1459                 :             {
    1460 GIC          15 :                 CommentStmt *stmt = makeNode(CommentStmt);
    1461                 : 
    1462              15 :                 stmt->objtype = OBJECT_TABCONSTRAINT;
    1463              15 :                 stmt->object = (Node *) list_make3(makeString(heapRel->schemaname),
    1464                 :                                                    makeString(heapRel->relname),
    1465                 :                                                    makeString(n->conname));
    1466              15 :                 stmt->comment = comment;
    1467                 : 
    1468              15 :                 result = lappend(result, stmt);
    1469 ECB             :             }
    1470 EUB             :         }
    1471                 :     }
    1472                 : 
    1473                 :     /*
    1474                 :      * Copy NOT NULL constraints, too (these do not require any option to have
    1475                 :      * been given).
    1476                 :      */
    1477 GNC         390 :     foreach(lc, RelationGetNotNullConstraints(relation, false))
    1478                 :     {
    1479                 :         AlterTableCmd *atsubcmd;
    1480                 : 
    1481              77 :         atsubcmd = makeNode(AlterTableCmd);
    1482              77 :         atsubcmd->subtype = AT_AddConstraint;
    1483              77 :         atsubcmd->def = (Node *) lfirst_node(Constraint, lc);
    1484              77 :         atsubcmds = lappend(atsubcmds, atsubcmd);
    1485                 :     }
    1486                 : 
    1487                 :     /*
    1488                 :      * If we generated any ALTER TABLE actions above, wrap them into a single
    1489                 :      * ALTER TABLE command.  Stick it at the front of the result, so it runs
    1490                 :      * before any CommentStmts we made above.
    1491 ECB             :      */
    1492 GIC         313 :     if (atsubcmds)
    1493                 :     {
    1494             107 :         AlterTableStmt *atcmd = makeNode(AlterTableStmt);
    1495                 : 
    1496             107 :         atcmd->relation = copyObject(heapRel);
    1497             107 :         atcmd->cmds = atsubcmds;
    1498             107 :         atcmd->objtype = OBJECT_TABLE;
    1499             107 :         atcmd->missing_ok = false;
    1500 CBC         107 :         result = lcons(atcmd, result);
    1501                 :     }
    1502                 : 
    1503                 :     /*
    1504                 :      * Process indexes if required.
    1505 ECB             :      */
    1506 GIC         313 :     if ((table_like_clause->options & CREATE_TABLE_LIKE_INDEXES) &&
    1507 CBC          40 :         relation->rd_rel->relhasindex)
    1508 ECB             :     {
    1509                 :         List       *parent_indexes;
    1510                 :         ListCell   *l;
    1511                 : 
    1512 GIC          31 :         parent_indexes = RelationGetIndexList(relation);
    1513                 : 
    1514              87 :         foreach(l, parent_indexes)
    1515 ECB             :         {
    1516 GIC          56 :             Oid         parent_index_oid = lfirst_oid(l);
    1517                 :             Relation    parent_index;
    1518                 :             IndexStmt  *index_stmt;
    1519                 : 
    1520              56 :             parent_index = index_open(parent_index_oid, AccessShareLock);
    1521                 : 
    1522                 :             /* Build CREATE INDEX statement to recreate the parent_index */
    1523              56 :             index_stmt = generateClonedIndexStmt(heapRel,
    1524                 :                                                  parent_index,
    1525                 :                                                  attmap,
    1526 ECB             :                                                  NULL);
    1527 EUB             : 
    1528                 :             /* Copy comment on index, if requested */
    1529 GIC          56 :             if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
    1530                 :             {
    1531              33 :                 comment = GetComment(parent_index_oid, RelationRelationId, 0);
    1532                 : 
    1533                 :                 /*
    1534 ECB             :                  * We make use of IndexStmt's idxcomment option, so as not to
    1535                 :                  * need to know now what name the index will have.
    1536                 :                  */
    1537 CBC          33 :                 index_stmt->idxcomment = comment;
    1538 ECB             :             }
    1539                 : 
    1540 CBC          56 :             result = lappend(result, index_stmt);
    1541                 : 
    1542 GIC          56 :             index_close(parent_index, AccessShareLock);
    1543 ECB             :         }
    1544                 :     }
    1545                 : 
    1546                 :     /* Done with child rel */
    1547 CBC         313 :     table_close(childrel, NoLock);
    1548 ECB             : 
    1549                 :     /*
    1550                 :      * Close the parent rel, but keep our AccessShareLock on it until xact
    1551                 :      * commit.  That will prevent someone else from deleting or ALTERing the
    1552                 :      * parent before the child is committed.
    1553                 :      */
    1554 CBC         313 :     table_close(relation, NoLock);
    1555                 : 
    1556 GIC         313 :     return result;
    1557                 : }
    1558 ECB             : 
    1559                 : static void
    1560 CBC          55 : transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
    1561 ECB             : {
    1562                 :     HeapTuple   tuple;
    1563                 :     TupleDesc   tupdesc;
    1564                 :     int         i;
    1565                 :     Oid         ofTypeId;
    1566                 : 
    1567 GNC          55 :     Assert(ofTypename);
    1568                 : 
    1569 GIC          55 :     tuple = typenameType(NULL, ofTypename, NULL);
    1570              52 :     check_of_type(tuple);
    1571              49 :     ofTypeId = ((Form_pg_type) GETSTRUCT(tuple))->oid;
    1572              49 :     ofTypename->typeOid = ofTypeId; /* cached for later */
    1573                 : 
    1574              49 :     tupdesc = lookup_rowtype_tupdesc(ofTypeId, -1);
    1575 CBC         144 :     for (i = 0; i < tupdesc->natts; i++)
    1576                 :     {
    1577 GIC          95 :         Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
    1578                 :         ColumnDef  *n;
    1579 ECB             : 
    1580 CBC          95 :         if (attr->attisdropped)
    1581 LBC           0 :             continue;
    1582 ECB             : 
    1583 GIC          95 :         n = makeNode(ColumnDef);
    1584              95 :         n->colname = pstrdup(NameStr(attr->attname));
    1585              95 :         n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod);
    1586              95 :         n->inhcount = 0;
    1587              95 :         n->is_local = true;
    1588              95 :         n->is_not_null = false;
    1589              95 :         n->is_from_type = true;
    1590 CBC          95 :         n->storage = 0;
    1591 GIC          95 :         n->raw_default = NULL;
    1592 CBC          95 :         n->cooked_default = NULL;
    1593 GIC          95 :         n->collClause = NULL;
    1594 CBC          95 :         n->collOid = attr->attcollation;
    1595              95 :         n->constraints = NIL;
    1596              95 :         n->location = -1;
    1597              95 :         cxt->columns = lappend(cxt->columns, n);
    1598 ECB             :     }
    1599 GIC          49 :     ReleaseTupleDesc(tupdesc);
    1600                 : 
    1601              49 :     ReleaseSysCache(tuple);
    1602              49 : }
    1603                 : 
    1604 ECB             : /*
    1605                 :  * Generate an IndexStmt node using information from an already existing index
    1606                 :  * "source_idx".
    1607                 :  *
    1608                 :  * heapRel is stored into the IndexStmt's relation field, but we don't use it
    1609                 :  * otherwise; some callers pass NULL, if they don't need it to be valid.
    1610                 :  * (The target relation might not exist yet, so we mustn't try to access it.)
    1611                 :  *
    1612                 :  * Attribute numbers in expression Vars are adjusted according to attmap.
    1613                 :  *
    1614                 :  * If constraintOid isn't NULL, we store the OID of any constraint associated
    1615                 :  * with the index there.
    1616                 :  *
    1617                 :  * Unlike transformIndexConstraint, we don't make any effort to force primary
    1618                 :  * key columns to be NOT NULL.  The larger cloning process this is part of
    1619                 :  * should have cloned their NOT NULL status separately (and DefineIndex will
    1620                 :  * complain if that fails to happen).
    1621                 :  */
    1622                 : IndexStmt *
    1623 GIC         759 : generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
    1624                 :                         const AttrMap *attmap,
    1625                 :                         Oid *constraintOid)
    1626                 : {
    1627 CBC         759 :     Oid         source_relid = RelationGetRelid(source_idx);
    1628                 :     HeapTuple   ht_idxrel;
    1629 ECB             :     HeapTuple   ht_idx;
    1630                 :     HeapTuple   ht_am;
    1631                 :     Form_pg_class idxrelrec;
    1632                 :     Form_pg_index idxrec;
    1633                 :     Form_pg_am  amrec;
    1634                 :     oidvector  *indcollation;
    1635                 :     oidvector  *indclass;
    1636                 :     IndexStmt  *index;
    1637                 :     List       *indexprs;
    1638                 :     ListCell   *indexpr_item;
    1639                 :     Oid         indrelid;
    1640                 :     int         keyno;
    1641                 :     Oid         keycoltype;
    1642                 :     Datum       datum;
    1643                 :     bool        isnull;
    1644                 : 
    1645 CBC         759 :     if (constraintOid)
    1646 GIC         703 :         *constraintOid = InvalidOid;
    1647                 : 
    1648                 :     /*
    1649                 :      * Fetch pg_class tuple of source index.  We can't use the copy in the
    1650                 :      * relcache entry because it doesn't include optional fields.
    1651                 :      */
    1652 CBC         759 :     ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(source_relid));
    1653 GIC         759 :     if (!HeapTupleIsValid(ht_idxrel))
    1654 LBC           0 :         elog(ERROR, "cache lookup failed for relation %u", source_relid);
    1655 GIC         759 :     idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
    1656                 : 
    1657                 :     /* Fetch pg_index tuple for source index from relcache entry */
    1658 CBC         759 :     ht_idx = source_idx->rd_indextuple;
    1659 GIC         759 :     idxrec = (Form_pg_index) GETSTRUCT(ht_idx);
    1660             759 :     indrelid = idxrec->indrelid;
    1661                 : 
    1662                 :     /* Fetch the pg_am tuple of the index' access method */
    1663             759 :     ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
    1664             759 :     if (!HeapTupleIsValid(ht_am))
    1665 LBC           0 :         elog(ERROR, "cache lookup failed for access method %u",
    1666                 :              idxrelrec->relam);
    1667 CBC         759 :     amrec = (Form_pg_am) GETSTRUCT(ht_am);
    1668 ECB             : 
    1669                 :     /* Extract indcollation from the pg_index tuple */
    1670 GNC         759 :     datum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
    1671                 :                                    Anum_pg_index_indcollation);
    1672 CBC         759 :     indcollation = (oidvector *) DatumGetPointer(datum);
    1673                 : 
    1674 ECB             :     /* Extract indclass from the pg_index tuple */
    1675 GNC         759 :     datum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx, Anum_pg_index_indclass);
    1676 GBC         759 :     indclass = (oidvector *) DatumGetPointer(datum);
    1677                 : 
    1678 ECB             :     /* Begin building the IndexStmt */
    1679 CBC         759 :     index = makeNode(IndexStmt);
    1680             759 :     index->relation = heapRel;
    1681             759 :     index->accessMethod = pstrdup(NameStr(amrec->amname));
    1682             759 :     if (OidIsValid(idxrelrec->reltablespace))
    1683               3 :         index->tableSpace = get_tablespace_name(idxrelrec->reltablespace);
    1684 ECB             :     else
    1685 CBC         756 :         index->tableSpace = NULL;
    1686             759 :     index->excludeOpNames = NIL;
    1687             759 :     index->idxcomment = NULL;
    1688             759 :     index->indexOid = InvalidOid;
    1689 GNC         759 :     index->oldNumber = InvalidRelFileNumber;
    1690 CBC         759 :     index->oldCreateSubid = InvalidSubTransactionId;
    1691 GNC         759 :     index->oldFirstRelfilelocatorSubid = InvalidSubTransactionId;
    1692 CBC         759 :     index->unique = idxrec->indisunique;
    1693 GIC         759 :     index->nulls_not_distinct = idxrec->indnullsnotdistinct;
    1694 CBC         759 :     index->primary = idxrec->indisprimary;
    1695 GIC         759 :     index->transformed = true;   /* don't need transformIndexStmt */
    1696 CBC         759 :     index->concurrent = false;
    1697             759 :     index->if_not_exists = false;
    1698 GIC         759 :     index->reset_default_tblspc = false;
    1699                 : 
    1700                 :     /*
    1701                 :      * We don't try to preserve the name of the source index; instead, just
    1702                 :      * let DefineIndex() choose a reasonable name.  (If we tried to preserve
    1703                 :      * the name, we'd get duplicate-relation-name failures unless the source
    1704                 :      * table was in a different schema.)
    1705                 :      */
    1706             759 :     index->idxname = NULL;
    1707                 : 
    1708                 :     /*
    1709                 :      * If the index is marked PRIMARY or has an exclusion condition, it's
    1710                 :      * certainly from a constraint; else, if it's not marked UNIQUE, it
    1711                 :      * certainly isn't.  If it is or might be from a constraint, we have to
    1712                 :      * fetch the pg_constraint record.
    1713                 :      */
    1714             759 :     if (index->primary || index->unique || idxrec->indisexclusion)
    1715             580 :     {
    1716             580 :         Oid         constraintId = get_index_constraint(source_relid);
    1717                 : 
    1718 CBC         580 :         if (OidIsValid(constraintId))
    1719                 :         {
    1720                 :             HeapTuple   ht_constr;
    1721                 :             Form_pg_constraint conrec;
    1722 ECB             : 
    1723 GIC         562 :             if (constraintOid)
    1724             536 :                 *constraintOid = constraintId;
    1725                 : 
    1726             562 :             ht_constr = SearchSysCache1(CONSTROID,
    1727                 :                                         ObjectIdGetDatum(constraintId));
    1728             562 :             if (!HeapTupleIsValid(ht_constr))
    1729 UIC           0 :                 elog(ERROR, "cache lookup failed for constraint %u",
    1730                 :                      constraintId);
    1731 GIC         562 :             conrec = (Form_pg_constraint) GETSTRUCT(ht_constr);
    1732                 : 
    1733             562 :             index->isconstraint = true;
    1734             562 :             index->deferrable = conrec->condeferrable;
    1735             562 :             index->initdeferred = conrec->condeferred;
    1736                 : 
    1737                 :             /* If it's an exclusion constraint, we need the operator names */
    1738             562 :             if (idxrec->indisexclusion)
    1739                 :             {
    1740 ECB             :                 Datum      *elems;
    1741                 :                 int         nElems;
    1742                 :                 int         i;
    1743                 : 
    1744 GIC           1 :                 Assert(conrec->contype == CONSTRAINT_EXCLUSION);
    1745                 :                 /* Extract operator OIDs from the pg_constraint tuple */
    1746 GNC           1 :                 datum = SysCacheGetAttrNotNull(CONSTROID, ht_constr,
    1747                 :                                                Anum_pg_constraint_conexclop);
    1748               1 :                 deconstruct_array_builtin(DatumGetArrayTypeP(datum), OIDOID, &elems, NULL, &nElems);
    1749                 : 
    1750 GIC           2 :                 for (i = 0; i < nElems; i++)
    1751 ECB             :                 {
    1752 CBC           1 :                     Oid         operid = DatumGetObjectId(elems[i]);
    1753 EUB             :                     HeapTuple   opertup;
    1754                 :                     Form_pg_operator operform;
    1755 ECB             :                     char       *oprname;
    1756                 :                     char       *nspname;
    1757                 :                     List       *namelist;
    1758                 : 
    1759 GIC           1 :                     opertup = SearchSysCache1(OPEROID,
    1760 ECB             :                                               ObjectIdGetDatum(operid));
    1761 GIC           1 :                     if (!HeapTupleIsValid(opertup))
    1762 UIC           0 :                         elog(ERROR, "cache lookup failed for operator %u",
    1763 ECB             :                              operid);
    1764 CBC           1 :                     operform = (Form_pg_operator) GETSTRUCT(opertup);
    1765 GIC           1 :                     oprname = pstrdup(NameStr(operform->oprname));
    1766                 :                     /* For simplicity we always schema-qualify the op name */
    1767 CBC           1 :                     nspname = get_namespace_name(operform->oprnamespace);
    1768               1 :                     namelist = list_make2(makeString(nspname),
    1769 ECB             :                                           makeString(oprname));
    1770 CBC           1 :                     index->excludeOpNames = lappend(index->excludeOpNames,
    1771 ECB             :                                                     namelist);
    1772 GIC           1 :                     ReleaseSysCache(opertup);
    1773 ECB             :                 }
    1774                 :             }
    1775                 : 
    1776 CBC         562 :             ReleaseSysCache(ht_constr);
    1777 ECB             :         }
    1778                 :         else
    1779 CBC          18 :             index->isconstraint = false;
    1780 ECB             :     }
    1781                 :     else
    1782 CBC         179 :         index->isconstraint = false;
    1783 ECB             : 
    1784                 :     /* Get the index expressions, if any */
    1785 CBC         759 :     datum = SysCacheGetAttr(INDEXRELID, ht_idx,
    1786 ECB             :                             Anum_pg_index_indexprs, &isnull);
    1787 GIC         759 :     if (!isnull)
    1788                 :     {
    1789                 :         char       *exprsString;
    1790                 : 
    1791              39 :         exprsString = TextDatumGetCString(datum);
    1792              39 :         indexprs = (List *) stringToNode(exprsString);
    1793                 :     }
    1794 ECB             :     else
    1795 GIC         720 :         indexprs = NIL;
    1796                 : 
    1797                 :     /* Build the list of IndexElem */
    1798             759 :     index->indexParams = NIL;
    1799             759 :     index->indexIncludingParams = NIL;
    1800                 : 
    1801             759 :     indexpr_item = list_head(indexprs);
    1802 CBC        1620 :     for (keyno = 0; keyno < idxrec->indnkeyatts; keyno++)
    1803 ECB             :     {
    1804                 :         IndexElem  *iparam;
    1805 GIC         861 :         AttrNumber  attnum = idxrec->indkey.values[keyno];
    1806 CBC         861 :         Form_pg_attribute attr = TupleDescAttr(RelationGetDescr(source_idx),
    1807                 :                                                keyno);
    1808 GIC         861 :         int16       opt = source_idx->rd_indoption[keyno];
    1809                 : 
    1810             861 :         iparam = makeNode(IndexElem);
    1811 ECB             : 
    1812 CBC         861 :         if (AttributeNumberIsValid(attnum))
    1813                 :         {
    1814 ECB             :             /* Simple index column */
    1815                 :             char       *attname;
    1816                 : 
    1817 GBC         822 :             attname = get_attname(indrelid, attnum, false);
    1818 GIC         822 :             keycoltype = get_atttype(indrelid, attnum);
    1819 ECB             : 
    1820 GIC         822 :             iparam->name = attname;
    1821 CBC         822 :             iparam->expr = NULL;
    1822 ECB             :         }
    1823                 :         else
    1824                 :         {
    1825                 :             /* Expressional index */
    1826                 :             Node       *indexkey;
    1827                 :             bool        found_whole_row;
    1828                 : 
    1829 GIC          39 :             if (indexpr_item == NULL)
    1830 UIC           0 :                 elog(ERROR, "too few entries in indexprs list");
    1831 GIC          39 :             indexkey = (Node *) lfirst(indexpr_item);
    1832 CBC          39 :             indexpr_item = lnext(indexprs, indexpr_item);
    1833                 : 
    1834 ECB             :             /* Adjust Vars to match new table's column numbering */
    1835 GIC          39 :             indexkey = map_variable_attnos(indexkey,
    1836 ECB             :                                            1, 0,
    1837                 :                                            attmap,
    1838                 :                                            InvalidOid, &found_whole_row);
    1839                 : 
    1840                 :             /* As in expandTableLikeClause, reject whole-row variables */
    1841 GIC          39 :             if (found_whole_row)
    1842 UIC           0 :                 ereport(ERROR,
    1843                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1844                 :                          errmsg("cannot convert whole-row table reference"),
    1845                 :                          errdetail("Index \"%s\" contains a whole-row table reference.",
    1846                 :                                    RelationGetRelationName(source_idx))));
    1847 ECB             : 
    1848 GIC          39 :             iparam->name = NULL;
    1849 CBC          39 :             iparam->expr = indexkey;
    1850 EUB             : 
    1851 GIC          39 :             keycoltype = exprType(indexkey);
    1852 ECB             :         }
    1853                 : 
    1854                 :         /* Copy the original index column name */
    1855 CBC         861 :         iparam->indexcolname = pstrdup(NameStr(attr->attname));
    1856 ECB             : 
    1857                 :         /* Add the collation name, if non-default */
    1858 CBC         861 :         iparam->collation = get_collation(indcollation->values[keyno], keycoltype);
    1859                 : 
    1860 ECB             :         /* Add the operator class name, if non-default */
    1861 GIC         861 :         iparam->opclass = get_opclass(indclass->values[keyno], keycoltype);
    1862             861 :         iparam->opclassopts =
    1863             861 :             untransformRelOptions(get_attoptions(source_relid, keyno + 1));
    1864 ECB             : 
    1865 GIC         861 :         iparam->ordering = SORTBY_DEFAULT;
    1866             861 :         iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
    1867 ECB             : 
    1868                 :         /* Adjust options if necessary */
    1869 GIC         861 :         if (source_idx->rd_indam->amcanorder)
    1870 ECB             :         {
    1871                 :             /*
    1872                 :              * If it supports sort ordering, copy DESC and NULLS opts. Don't
    1873                 :              * set non-default settings unnecessarily, though, so as to
    1874                 :              * improve the chance of recognizing equivalence to constraint
    1875                 :              * indexes.
    1876                 :              */
    1877 GIC         861 :             if (opt & INDOPTION_DESC)
    1878                 :             {
    1879 LBC           0 :                 iparam->ordering = SORTBY_DESC;
    1880               0 :                 if ((opt & INDOPTION_NULLS_FIRST) == 0)
    1881 UIC           0 :                     iparam->nulls_ordering = SORTBY_NULLS_LAST;
    1882                 :             }
    1883 ECB             :             else
    1884                 :             {
    1885 GIC         861 :                 if (opt & INDOPTION_NULLS_FIRST)
    1886 LBC           0 :                     iparam->nulls_ordering = SORTBY_NULLS_FIRST;
    1887 ECB             :             }
    1888                 :         }
    1889                 : 
    1890 CBC         861 :         index->indexParams = lappend(index->indexParams, iparam);
    1891                 :     }
    1892                 : 
    1893 ECB             :     /* Handle included columns separately */
    1894 CBC         768 :     for (keyno = idxrec->indnkeyatts; keyno < idxrec->indnatts; keyno++)
    1895                 :     {
    1896 ECB             :         IndexElem  *iparam;
    1897 GIC           9 :         AttrNumber  attnum = idxrec->indkey.values[keyno];
    1898 CBC           9 :         Form_pg_attribute attr = TupleDescAttr(RelationGetDescr(source_idx),
    1899                 :                                                keyno);
    1900 ECB             : 
    1901 GIC           9 :         iparam = makeNode(IndexElem);
    1902                 : 
    1903               9 :         if (AttributeNumberIsValid(attnum))
    1904                 :         {
    1905 ECB             :             /* Simple index column */
    1906                 :             char       *attname;
    1907                 : 
    1908 CBC           9 :             attname = get_attname(indrelid, attnum, false);
    1909 ECB             : 
    1910 GIC           9 :             iparam->name = attname;
    1911               9 :             iparam->expr = NULL;
    1912                 :         }
    1913                 :         else
    1914 UIC           0 :             ereport(ERROR,
    1915                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1916                 :                      errmsg("expressions are not supported in included columns")));
    1917 ECB             : 
    1918 EUB             :         /* Copy the original index column name */
    1919 CBC           9 :         iparam->indexcolname = pstrdup(NameStr(attr->attname));
    1920 ECB             : 
    1921 GIC           9 :         index->indexIncludingParams = lappend(index->indexIncludingParams, iparam);
    1922                 :     }
    1923 ECB             :     /* Copy reloptions if any */
    1924 GIC         759 :     datum = SysCacheGetAttr(RELOID, ht_idxrel,
    1925                 :                             Anum_pg_class_reloptions, &isnull);
    1926             759 :     if (!isnull)
    1927 UIC           0 :         index->options = untransformRelOptions(datum);
    1928                 : 
    1929 ECB             :     /* If it's a partial index, decompile and append the predicate */
    1930 GBC         759 :     datum = SysCacheGetAttr(INDEXRELID, ht_idx,
    1931                 :                             Anum_pg_index_indpred, &isnull);
    1932 GIC         759 :     if (!isnull)
    1933                 :     {
    1934                 :         char       *pred_str;
    1935                 :         Node       *pred_tree;
    1936 ECB             :         bool        found_whole_row;
    1937                 : 
    1938                 :         /* Convert text string to node tree */
    1939 CBC           9 :         pred_str = TextDatumGetCString(datum);
    1940 GIC           9 :         pred_tree = (Node *) stringToNode(pred_str);
    1941                 : 
    1942                 :         /* Adjust Vars to match new table's column numbering */
    1943 CBC           9 :         pred_tree = map_variable_attnos(pred_tree,
    1944                 :                                         1, 0,
    1945                 :                                         attmap,
    1946 ECB             :                                         InvalidOid, &found_whole_row);
    1947                 : 
    1948                 :         /* As in expandTableLikeClause, reject whole-row variables */
    1949 CBC           9 :         if (found_whole_row)
    1950 LBC           0 :             ereport(ERROR,
    1951 ECB             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1952                 :                      errmsg("cannot convert whole-row table reference"),
    1953                 :                      errdetail("Index \"%s\" contains a whole-row table reference.",
    1954                 :                                RelationGetRelationName(source_idx))));
    1955                 : 
    1956 GIC           9 :         index->whereClause = pred_tree;
    1957 ECB             :     }
    1958                 : 
    1959                 :     /* Clean up */
    1960 GIC         759 :     ReleaseSysCache(ht_idxrel);
    1961             759 :     ReleaseSysCache(ht_am);
    1962                 : 
    1963             759 :     return index;
    1964                 : }
    1965 ECB             : 
    1966                 : /*
    1967 EUB             :  * Generate a CreateStatsStmt node using information from an already existing
    1968                 :  * extended statistic "source_statsid", for the rel identified by heapRel and
    1969                 :  * heapRelid.
    1970                 :  */
    1971                 : static CreateStatsStmt *
    1972 GIC          18 : generateClonedExtStatsStmt(RangeVar *heapRel, Oid heapRelid,
    1973 ECB             :                            Oid source_statsid)
    1974 EUB             : {
    1975                 :     HeapTuple   ht_stats;
    1976                 :     Form_pg_statistic_ext statsrec;
    1977                 :     CreateStatsStmt *stats;
    1978 CBC          18 :     List       *stat_types = NIL;
    1979 GIC          18 :     List       *def_names = NIL;
    1980                 :     bool        isnull;
    1981                 :     Datum       datum;
    1982 ECB             :     ArrayType  *arr;
    1983                 :     char       *enabled;
    1984                 :     int         i;
    1985                 : 
    1986 CBC          18 :     Assert(OidIsValid(heapRelid));
    1987 GIC          18 :     Assert(heapRel != NULL);
    1988                 : 
    1989 ECB             :     /*
    1990                 :      * Fetch pg_statistic_ext tuple of source statistics object.
    1991                 :      */
    1992 GIC          18 :     ht_stats = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(source_statsid));
    1993              18 :     if (!HeapTupleIsValid(ht_stats))
    1994 UIC           0 :         elog(ERROR, "cache lookup failed for statistics object %u", source_statsid);
    1995 GIC          18 :     statsrec = (Form_pg_statistic_ext) GETSTRUCT(ht_stats);
    1996 ECB             : 
    1997                 :     /* Determine which statistics types exist */
    1998 GNC          18 :     datum = SysCacheGetAttrNotNull(STATEXTOID, ht_stats,
    1999                 :                                    Anum_pg_statistic_ext_stxkind);
    2000 GIC          18 :     arr = DatumGetArrayTypeP(datum);
    2001 GBC          18 :     if (ARR_NDIM(arr) != 1 ||
    2002 GIC          18 :         ARR_HASNULL(arr) ||
    2003              18 :         ARR_ELEMTYPE(arr) != CHAROID)
    2004 UIC           0 :         elog(ERROR, "stxkind is not a 1-D char array");
    2005 GIC          18 :     enabled = (char *) ARR_DATA_PTR(arr);
    2006 CBC          54 :     for (i = 0; i < ARR_DIMS(arr)[0]; i++)
    2007                 :     {
    2008              36 :         if (enabled[i] == STATS_EXT_NDISTINCT)
    2009 GIC           9 :             stat_types = lappend(stat_types, makeString("ndistinct"));
    2010              27 :         else if (enabled[i] == STATS_EXT_DEPENDENCIES)
    2011 CBC           9 :             stat_types = lappend(stat_types, makeString("dependencies"));
    2012 GIC          18 :         else if (enabled[i] == STATS_EXT_MCV)
    2013 CBC           9 :             stat_types = lappend(stat_types, makeString("mcv"));
    2014 GBC           9 :         else if (enabled[i] == STATS_EXT_EXPRESSIONS)
    2015                 :             /* expression stats are not exposed to users */
    2016 GIC           9 :             continue;
    2017 ECB             :         else
    2018 UIC           0 :             elog(ERROR, "unrecognized statistics kind %c", enabled[i]);
    2019 ECB             :     }
    2020                 : 
    2021                 :     /* Determine which columns the statistics are on */
    2022 GIC          36 :     for (i = 0; i < statsrec->stxkeys.dim1; i++)
    2023                 :     {
    2024              18 :         StatsElem  *selem = makeNode(StatsElem);
    2025              18 :         AttrNumber  attnum = statsrec->stxkeys.values[i];
    2026 ECB             : 
    2027 CBC          18 :         selem->name = get_attname(heapRelid, attnum, false);
    2028 GIC          18 :         selem->expr = NULL;
    2029                 : 
    2030 CBC          18 :         def_names = lappend(def_names, selem);
    2031                 :     }
    2032                 : 
    2033                 :     /*
    2034                 :      * Now handle expressions, if there are any. The order (with respect to
    2035                 :      * regular attributes) does not really matter for extended stats, so we
    2036 ECB             :      * simply append them after simple column references.
    2037 EUB             :      *
    2038                 :      * XXX Some places during build/estimation treat expressions as if they
    2039                 :      * are before attributes, but for the CREATE command that's entirely
    2040                 :      * irrelevant.
    2041                 :      */
    2042 GIC          18 :     datum = SysCacheGetAttr(STATEXTOID, ht_stats,
    2043 ECB             :                             Anum_pg_statistic_ext_stxexprs, &isnull);
    2044                 : 
    2045 GIC          18 :     if (!isnull)
    2046                 :     {
    2047 ECB             :         ListCell   *lc;
    2048 CBC           9 :         List       *exprs = NIL;
    2049                 :         char       *exprsString;
    2050 ECB             : 
    2051 GIC           9 :         exprsString = TextDatumGetCString(datum);
    2052               9 :         exprs = (List *) stringToNode(exprsString);
    2053                 : 
    2054              18 :         foreach(lc, exprs)
    2055                 :         {
    2056               9 :             StatsElem  *selem = makeNode(StatsElem);
    2057                 : 
    2058               9 :             selem->name = NULL;
    2059 CBC           9 :             selem->expr = (Node *) lfirst(lc);
    2060                 : 
    2061 GIC           9 :             def_names = lappend(def_names, selem);
    2062                 :         }
    2063                 : 
    2064               9 :         pfree(exprsString);
    2065 ECB             :     }
    2066                 : 
    2067                 :     /* finally, build the output node */
    2068 GIC          18 :     stats = makeNode(CreateStatsStmt);
    2069              18 :     stats->defnames = NULL;
    2070              18 :     stats->stat_types = stat_types;
    2071              18 :     stats->exprs = def_names;
    2072              18 :     stats->relations = list_make1(heapRel);
    2073 CBC          18 :     stats->stxcomment = NULL;
    2074              18 :     stats->transformed = true;   /* don't need transformStatsStmt again */
    2075 GIC          18 :     stats->if_not_exists = false;
    2076                 : 
    2077                 :     /* Clean up */
    2078              18 :     ReleaseSysCache(ht_stats);
    2079 ECB             : 
    2080 CBC          18 :     return stats;
    2081 EUB             : }
    2082 ECB             : 
    2083                 : /*
    2084                 :  * get_collation        - fetch qualified name of a collation
    2085                 :  *
    2086                 :  * If collation is InvalidOid or is the default for the given actual_datatype,
    2087                 :  * then the return value is NIL.
    2088                 :  */
    2089                 : static List *
    2090 CBC         861 : get_collation(Oid collation, Oid actual_datatype)
    2091 EUB             : {
    2092 ECB             :     List       *result;
    2093                 :     HeapTuple   ht_coll;
    2094                 :     Form_pg_collation coll_rec;
    2095                 :     char       *nsp_name;
    2096                 :     char       *coll_name;
    2097                 : 
    2098 CBC         861 :     if (!OidIsValid(collation))
    2099             786 :         return NIL;             /* easy case */
    2100              75 :     if (collation == get_typcollation(actual_datatype))
    2101              72 :         return NIL;             /* just let it default */
    2102                 : 
    2103               3 :     ht_coll = SearchSysCache1(COLLOID, ObjectIdGetDatum(collation));
    2104 GIC           3 :     if (!HeapTupleIsValid(ht_coll))
    2105 UBC           0 :         elog(ERROR, "cache lookup failed for collation %u", collation);
    2106 GIC           3 :     coll_rec = (Form_pg_collation) GETSTRUCT(ht_coll);
    2107                 : 
    2108                 :     /* For simplicity, we always schema-qualify the name */
    2109 CBC           3 :     nsp_name = get_namespace_name(coll_rec->collnamespace);
    2110 GIC           3 :     coll_name = pstrdup(NameStr(coll_rec->collname));
    2111 CBC           3 :     result = list_make2(makeString(nsp_name), makeString(coll_name));
    2112 ECB             : 
    2113 GIC           3 :     ReleaseSysCache(ht_coll);
    2114 CBC           3 :     return result;
    2115 ECB             : }
    2116                 : 
    2117                 : /*
    2118                 :  * get_opclass          - fetch qualified name of an index operator class
    2119                 :  *
    2120                 :  * If the opclass is the default for the given actual_datatype, then
    2121                 :  * the return value is NIL.
    2122                 :  */
    2123                 : static List *
    2124 GIC         861 : get_opclass(Oid opclass, Oid actual_datatype)
    2125                 : {
    2126             861 :     List       *result = NIL;
    2127                 :     HeapTuple   ht_opc;
    2128                 :     Form_pg_opclass opc_rec;
    2129 ECB             : 
    2130 GIC         861 :     ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
    2131             861 :     if (!HeapTupleIsValid(ht_opc))
    2132 LBC           0 :         elog(ERROR, "cache lookup failed for opclass %u", opclass);
    2133 GIC         861 :     opc_rec = (Form_pg_opclass) GETSTRUCT(ht_opc);
    2134                 : 
    2135 CBC         861 :     if (GetDefaultOpClass(actual_datatype, opc_rec->opcmethod) != opclass)
    2136                 :     {
    2137                 :         /* For simplicity, we always schema-qualify the name */
    2138               3 :         char       *nsp_name = get_namespace_name(opc_rec->opcnamespace);
    2139               3 :         char       *opc_name = pstrdup(NameStr(opc_rec->opcname));
    2140                 : 
    2141               3 :         result = list_make2(makeString(nsp_name), makeString(opc_name));
    2142                 :     }
    2143 ECB             : 
    2144 GIC         861 :     ReleaseSysCache(ht_opc);
    2145 CBC         861 :     return result;
    2146 ECB             : }
    2147                 : 
    2148                 : 
    2149                 : /*
    2150                 :  * transformIndexConstraints
    2151                 :  *      Handle UNIQUE, PRIMARY KEY, EXCLUDE constraints, which create indexes.
    2152                 :  *      We also merge in any index definitions arising from
    2153                 :  *      LIKE ... INCLUDING INDEXES.
    2154                 :  */
    2155                 : static void
    2156 CBC       55506 : transformIndexConstraints(CreateStmtContext *cxt)
    2157 ECB             : {
    2158                 :     IndexStmt  *index;
    2159 CBC       55506 :     List       *indexlist = NIL;
    2160           55506 :     List       *finalindexlist = NIL;
    2161 ECB             :     ListCell   *lc;
    2162                 : 
    2163                 :     /*
    2164                 :      * Run through the constraints that need to generate an index, and do so.
    2165                 :      *
    2166                 :      * For PRIMARY KEY, in addition we set each column's attnotnull flag true.
    2167                 :      * We do not create a separate CHECK (IS NOT NULL) constraint, as that
    2168                 :      * would be redundant: the PRIMARY KEY constraint itself fulfills that
    2169                 :      * role.  Other constraint types don't need any NOT NULL markings.
    2170                 :      */
    2171 GIC       92557 :     foreach(lc, cxt->ixconstraints)
    2172                 :     {
    2173           37057 :         Constraint *constraint = lfirst_node(Constraint, lc);
    2174                 : 
    2175           37057 :         Assert(constraint->contype == CONSTR_PRIMARY ||
    2176                 :                constraint->contype == CONSTR_UNIQUE ||
    2177                 :                constraint->contype == CONSTR_EXCLUSION);
    2178                 : 
    2179 CBC       37057 :         index = transformIndexConstraint(constraint, cxt);
    2180                 : 
    2181 GIC       37051 :         indexlist = lappend(indexlist, index);
    2182                 :     }
    2183                 : 
    2184                 :     /*
    2185                 :      * Scan the index list and remove any redundant index specifications. This
    2186                 :      * can happen if, for instance, the user writes UNIQUE PRIMARY KEY. A
    2187 ECB             :      * strict reading of SQL would suggest raising an error instead, but that
    2188                 :      * strikes me as too anal-retentive. - tgl 2001-02-14
    2189                 :      *
    2190                 :      * XXX in ALTER TABLE case, it'd be nice to look for duplicate
    2191                 :      * pre-existing indexes, too.
    2192                 :      */
    2193 CBC       55500 :     if (cxt->pkey != NULL)
    2194 EUB             :     {
    2195 ECB             :         /* Make sure we keep the PKEY index in preference to others... */
    2196 GIC       22076 :         finalindexlist = list_make1(cxt->pkey);
    2197                 :     }
    2198 ECB             : 
    2199 CBC       92551 :     foreach(lc, indexlist)
    2200 ECB             :     {
    2201 GIC       37051 :         bool        keep = true;
    2202 ECB             :         ListCell   *k;
    2203                 : 
    2204 GIC       37051 :         index = lfirst(lc);
    2205                 : 
    2206                 :         /* if it's pkey, it's already in finalindexlist */
    2207           37051 :         if (index == cxt->pkey)
    2208           22076 :             continue;
    2209                 : 
    2210           15050 :         foreach(k, finalindexlist)
    2211                 :         {
    2212              75 :             IndexStmt  *priorindex = lfirst(k);
    2213 ECB             : 
    2214 GIC          78 :             if (equal(index->indexParams, priorindex->indexParams) &&
    2215 CBC           6 :                 equal(index->indexIncludingParams, priorindex->indexIncludingParams) &&
    2216 GIC           6 :                 equal(index->whereClause, priorindex->whereClause) &&
    2217               3 :                 equal(index->excludeOpNames, priorindex->excludeOpNames) &&
    2218               3 :                 strcmp(index->accessMethod, priorindex->accessMethod) == 0 &&
    2219 CBC           3 :                 index->nulls_not_distinct == priorindex->nulls_not_distinct &&
    2220               3 :                 index->deferrable == priorindex->deferrable &&
    2221 UBC           0 :                 index->initdeferred == priorindex->initdeferred)
    2222 ECB             :             {
    2223 UIC           0 :                 priorindex->unique |= index->unique;
    2224 ECB             : 
    2225                 :                 /*
    2226                 :                  * If the prior index is as yet unnamed, and this one is
    2227                 :                  * named, then transfer the name to the prior index. This
    2228                 :                  * ensures that if we have named and unnamed constraints,
    2229                 :                  * we'll use (at least one of) the names for the index.
    2230                 :                  */
    2231 UIC           0 :                 if (priorindex->idxname == NULL)
    2232               0 :                     priorindex->idxname = index->idxname;
    2233 LBC           0 :                 keep = false;
    2234               0 :                 break;
    2235                 :             }
    2236                 :         }
    2237                 : 
    2238 GIC       14975 :         if (keep)
    2239           14975 :             finalindexlist = lappend(finalindexlist, index);
    2240                 :     }
    2241                 : 
    2242                 :     /*
    2243                 :      * Now append all the IndexStmts to cxt->alist.
    2244                 :      */
    2245           55500 :     cxt->alist = list_concat(cxt->alist, finalindexlist);
    2246 CBC       55500 : }
    2247 ECB             : 
    2248                 : /*
    2249                 :  * transformIndexConstraint
    2250                 :  *      Transform one UNIQUE, PRIMARY KEY, or EXCLUDE constraint for
    2251                 :  *      transformIndexConstraints. An IndexStmt is returned.
    2252                 :  *
    2253                 :  * For a PRIMARY KEY constraint, we additionally force the columns to be
    2254                 :  * marked as NOT NULL, without producing a CHECK (IS NOT NULL) constraint.
    2255                 :  */
    2256                 : static IndexStmt *
    2257 GIC       37057 : transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
    2258 ECB             : {
    2259                 :     IndexStmt  *index;
    2260 CBC       37057 :     List       *notnullcmds = NIL;
    2261                 :     ListCell   *lc;
    2262                 : 
    2263 GIC       37057 :     index = makeNode(IndexStmt);
    2264 ECB             : 
    2265 GIC       37057 :     index->unique = (constraint->contype != CONSTR_EXCLUSION);
    2266 CBC       37057 :     index->primary = (constraint->contype == CONSTR_PRIMARY);
    2267 GIC       37057 :     if (index->primary)
    2268                 :     {
    2269           22076 :         if (cxt->pkey != NULL)
    2270 UIC           0 :             ereport(ERROR,
    2271                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    2272                 :                      errmsg("multiple primary keys for table \"%s\" are not allowed",
    2273                 :                             cxt->relation->relname),
    2274                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2275 GIC       22076 :         cxt->pkey = index;
    2276                 : 
    2277                 :         /*
    2278 ECB             :          * In ALTER TABLE case, a primary index might already exist, but
    2279                 :          * DefineIndex will check for it.
    2280                 :          */
    2281                 :     }
    2282 GIC       37057 :     index->nulls_not_distinct = constraint->nulls_not_distinct;
    2283           37057 :     index->isconstraint = true;
    2284 CBC       37057 :     index->deferrable = constraint->deferrable;
    2285 GIC       37057 :     index->initdeferred = constraint->initdeferred;
    2286 ECB             : 
    2287 GIC       37057 :     if (constraint->conname != NULL)
    2288             426 :         index->idxname = pstrdup(constraint->conname);
    2289 ECB             :     else
    2290 GIC       36631 :         index->idxname = NULL;   /* DefineIndex will choose name */
    2291                 : 
    2292 CBC       37057 :     index->relation = cxt->relation;
    2293           37057 :     index->accessMethod = constraint->access_method ? constraint->access_method : DEFAULT_INDEX_TYPE;
    2294 GIC       37057 :     index->options = constraint->options;
    2295 CBC       37057 :     index->tableSpace = constraint->indexspace;
    2296 GIC       37057 :     index->whereClause = constraint->where_clause;
    2297 CBC       37057 :     index->indexParams = NIL;
    2298 GIC       37057 :     index->indexIncludingParams = NIL;
    2299 CBC       37057 :     index->excludeOpNames = NIL;
    2300           37057 :     index->idxcomment = NULL;
    2301           37057 :     index->indexOid = InvalidOid;
    2302 GNC       37057 :     index->oldNumber = InvalidRelFileNumber;
    2303 CBC       37057 :     index->oldCreateSubid = InvalidSubTransactionId;
    2304 GNC       37057 :     index->oldFirstRelfilelocatorSubid = InvalidSubTransactionId;
    2305 CBC       37057 :     index->transformed = false;
    2306 GBC       37057 :     index->concurrent = false;
    2307 GIC       37057 :     index->if_not_exists = false;
    2308 GBC       37057 :     index->reset_default_tblspc = constraint->reset_default_tblspc;
    2309                 : 
    2310                 :     /*
    2311                 :      * If it's ALTER TABLE ADD CONSTRAINT USING INDEX, look up the index and
    2312                 :      * verify it's usable, then extract the implied column name list.  (We
    2313                 :      * will not actually need the column name list at runtime, but we need it
    2314                 :      * now to check for duplicate column entries below.)
    2315                 :      */
    2316           37057 :     if (constraint->indexname != NULL)
    2317 EUB             :     {
    2318 GBC       33367 :         char       *index_name = constraint->indexname;
    2319           33367 :         Relation    heap_rel = cxt->rel;
    2320                 :         Oid         index_oid;
    2321                 :         Relation    index_rel;
    2322                 :         Form_pg_index index_form;
    2323 ECB             :         oidvector  *indclass;
    2324                 :         Datum       indclassDatum;
    2325                 :         int         i;
    2326                 : 
    2327                 :         /* Grammar should not allow this with explicit column list */
    2328 GIC       33367 :         Assert(constraint->keys == NIL);
    2329 ECB             : 
    2330                 :         /* Grammar should only allow PRIMARY and UNIQUE constraints */
    2331 GIC       33367 :         Assert(constraint->contype == CONSTR_PRIMARY ||
    2332                 :                constraint->contype == CONSTR_UNIQUE);
    2333                 : 
    2334                 :         /* Must be ALTER, not CREATE, but grammar doesn't enforce that */
    2335           33367 :         if (!cxt->isalter)
    2336 UIC           0 :             ereport(ERROR,
    2337                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2338                 :                      errmsg("cannot use an existing index in CREATE TABLE"),
    2339                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2340                 : 
    2341 ECB             :         /* Look for the index in the same schema as the table */
    2342 GIC       33367 :         index_oid = get_relname_relid(index_name, RelationGetNamespace(heap_rel));
    2343                 : 
    2344 CBC       33367 :         if (!OidIsValid(index_oid))
    2345 UIC           0 :             ereport(ERROR,
    2346                 :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
    2347 ECB             :                      errmsg("index \"%s\" does not exist", index_name),
    2348                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2349                 : 
    2350                 :         /* Open the index (this will throw an error if it is not an index) */
    2351 CBC       33367 :         index_rel = index_open(index_oid, AccessShareLock);
    2352 GIC       33367 :         index_form = index_rel->rd_index;
    2353 ECB             : 
    2354 EUB             :         /* Check that it does not have an associated constraint already */
    2355 GIC       33367 :         if (OidIsValid(get_index_constraint(index_oid)))
    2356 UIC           0 :             ereport(ERROR,
    2357                 :                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    2358                 :                      errmsg("index \"%s\" is already associated with a constraint",
    2359 ECB             :                             index_name),
    2360                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2361                 : 
    2362                 :         /* Perform validity checks on the index */
    2363 GIC       33367 :         if (index_form->indrelid != RelationGetRelid(heap_rel))
    2364 UIC           0 :             ereport(ERROR,
    2365                 :                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    2366 ECB             :                      errmsg("index \"%s\" does not belong to table \"%s\"",
    2367                 :                             index_name, RelationGetRelationName(heap_rel)),
    2368                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2369                 : 
    2370 GIC       33367 :         if (!index_form->indisvalid)
    2371 LBC           0 :             ereport(ERROR,
    2372 ECB             :                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
    2373                 :                      errmsg("index \"%s\" is not valid", index_name),
    2374                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2375                 : 
    2376 CBC       33367 :         if (!index_form->indisunique)
    2377 LBC           0 :             ereport(ERROR,
    2378 ECB             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2379                 :                      errmsg("\"%s\" is not a unique index", index_name),
    2380                 :                      errdetail("Cannot create a primary key or unique constraint using such an index."),
    2381                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2382                 : 
    2383 CBC       33367 :         if (RelationGetIndexExpressions(index_rel) != NIL)
    2384 LBC           0 :             ereport(ERROR,
    2385 ECB             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2386                 :                      errmsg("index \"%s\" contains expressions", index_name),
    2387                 :                      errdetail("Cannot create a primary key or unique constraint using such an index."),
    2388                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2389                 : 
    2390 CBC       33367 :         if (RelationGetIndexPredicate(index_rel) != NIL)
    2391 LBC           0 :             ereport(ERROR,
    2392 ECB             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2393                 :                      errmsg("\"%s\" is a partial index", index_name),
    2394                 :                      errdetail("Cannot create a primary key or unique constraint using such an index."),
    2395                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2396                 : 
    2397                 :         /*
    2398                 :          * It's probably unsafe to change a deferred index to non-deferred. (A
    2399                 :          * non-constraint index couldn't be deferred anyway, so this case
    2400                 :          * should never occur; no need to sweat, but let's check it.)
    2401                 :          */
    2402 CBC       33367 :         if (!index_form->indimmediate && !constraint->deferrable)
    2403 LBC           0 :             ereport(ERROR,
    2404                 :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2405                 :                      errmsg("\"%s\" is a deferrable index", index_name),
    2406                 :                      errdetail("Cannot create a non-deferrable constraint using a deferrable index."),
    2407                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2408                 : 
    2409                 :         /*
    2410                 :          * Insist on it being a btree.  That's the only kind that supports
    2411                 :          * uniqueness at the moment anyway; but we must have an index that
    2412 ECB             :          * exactly matches what you'd get from plain ADD CONSTRAINT syntax,
    2413                 :          * else dump and reload will produce a different index (breaking
    2414                 :          * pg_upgrade in particular).
    2415                 :          */
    2416 GIC       33367 :         if (index_rel->rd_rel->relam != get_index_am_oid(DEFAULT_INDEX_TYPE, false))
    2417 UIC           0 :             ereport(ERROR,
    2418                 :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2419 ECB             :                      errmsg("index \"%s\" is not a btree", index_name),
    2420 EUB             :                      parser_errposition(cxt->pstate, constraint->location)));
    2421                 : 
    2422                 :         /* Must get indclass the hard way */
    2423 GNC       33367 :         indclassDatum = SysCacheGetAttrNotNull(INDEXRELID,
    2424           33367 :                                                index_rel->rd_indextuple,
    2425                 :                                                Anum_pg_index_indclass);
    2426 CBC       33367 :         indclass = (oidvector *) DatumGetPointer(indclassDatum);
    2427                 : 
    2428           88271 :         for (i = 0; i < index_form->indnatts; i++)
    2429 EUB             :         {
    2430 GIC       54910 :             int16       attnum = index_form->indkey.values[i];
    2431                 :             const FormData_pg_attribute *attform;
    2432                 :             char       *attname;
    2433                 :             Oid         defopclass;
    2434                 : 
    2435 ECB             :             /*
    2436                 :              * We shouldn't see attnum == 0 here, since we already rejected
    2437                 :              * expression indexes.  If we do, SystemAttributeDefinition will
    2438                 :              * throw an error.
    2439                 :              */
    2440 GBC       54910 :             if (attnum > 0)
    2441                 :             {
    2442 GIC       54910 :                 Assert(attnum <= heap_rel->rd_att->natts);
    2443           54910 :                 attform = TupleDescAttr(heap_rel->rd_att, attnum - 1);
    2444                 :             }
    2445                 :             else
    2446 UIC           0 :                 attform = SystemAttributeDefinition(attnum);
    2447 CBC       54910 :             attname = pstrdup(NameStr(attform->attname));
    2448 EUB             : 
    2449 GIC       54910 :             if (i < index_form->indnkeyatts)
    2450                 :             {
    2451                 :                 /*
    2452                 :                  * Insist on default opclass, collation, and sort options.
    2453                 :                  * While the index would still work as a constraint with
    2454 ECB             :                  * non-default settings, it might not provide exactly the same
    2455 EUB             :                  * uniqueness semantics as you'd get from a normally-created
    2456                 :                  * constraint; and there's also the dump/reload problem
    2457                 :                  * mentioned above.
    2458                 :                  */
    2459                 :                 Datum       attoptions =
    2460 CBC       54895 :                 get_attoptions(RelationGetRelid(index_rel), i + 1);
    2461 EUB             : 
    2462 GIC       54895 :                 defopclass = GetDefaultOpClass(attform->atttypid,
    2463           54895 :                                                index_rel->rd_rel->relam);
    2464           54895 :                 if (indclass->values[i] != defopclass ||
    2465           54895 :                     attform->attcollation != index_rel->rd_indcollation[i] ||
    2466           54892 :                     attoptions != (Datum) 0 ||
    2467 CBC       54892 :                     index_rel->rd_indoption[i] != 0)
    2468 GBC           6 :                     ereport(ERROR,
    2469                 :                             (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2470                 :                              errmsg("index \"%s\" column number %d does not have default sorting behavior", index_name, i + 1),
    2471                 :                              errdetail("Cannot create a primary key or unique constraint using such an index."),
    2472                 :                              parser_errposition(cxt->pstate, constraint->location)));
    2473                 : 
    2474 CBC       54889 :                 constraint->keys = lappend(constraint->keys, makeString(attname));
    2475 EUB             :             }
    2476                 :             else
    2477 GIC          15 :                 constraint->including = lappend(constraint->including, makeString(attname));
    2478                 :         }
    2479                 : 
    2480                 :         /* Close the index relation but keep the lock */
    2481           33361 :         relation_close(index_rel, NoLock);
    2482                 : 
    2483           33361 :         index->indexOid = index_oid;
    2484                 :     }
    2485                 : 
    2486 ECB             :     /*
    2487 EUB             :      * If it's an EXCLUDE constraint, the grammar returns a list of pairs of
    2488                 :      * IndexElems and operator names.  We have to break that apart into
    2489                 :      * separate lists.
    2490                 :      */
    2491 GIC       37051 :     if (constraint->contype == CONSTR_EXCLUSION)
    2492                 :     {
    2493             143 :         foreach(lc, constraint->exclusions)
    2494                 :         {
    2495              79 :             List       *pair = (List *) lfirst(lc);
    2496                 :             IndexElem  *elem;
    2497                 :             List       *opname;
    2498                 : 
    2499              79 :             Assert(list_length(pair) == 2);
    2500 CBC          79 :             elem = linitial_node(IndexElem, pair);
    2501 GBC          79 :             opname = lsecond_node(List, pair);
    2502                 : 
    2503 GIC          79 :             index->indexParams = lappend(index->indexParams, elem);
    2504              79 :             index->excludeOpNames = lappend(index->excludeOpNames, opname);
    2505                 :         }
    2506                 :     }
    2507 ECB             : 
    2508                 :     /*
    2509                 :      * For UNIQUE and PRIMARY KEY, we just have a list of column names.
    2510                 :      *
    2511                 :      * Make sure referenced keys exist.  If we are making a PRIMARY KEY index,
    2512                 :      * also make sure they are NOT NULL.
    2513                 :      */
    2514                 :     else
    2515                 :     {
    2516 GIC       95918 :         foreach(lc, constraint->keys)
    2517                 :         {
    2518           58931 :             char       *key = strVal(lfirst(lc));
    2519           58931 :             bool        found = false;
    2520           58931 :             ColumnDef  *column = NULL;
    2521                 :             ListCell   *columns;
    2522                 :             IndexElem  *iparam;
    2523 ECB             : 
    2524                 :             /* Make sure referenced column exists. */
    2525 CBC       59469 :             foreach(columns, cxt->columns)
    2526 ECB             :             {
    2527 GIC        3950 :                 column = lfirst_node(ColumnDef, columns);
    2528            3950 :                 if (strcmp(column->colname, key) == 0)
    2529 EUB             :                 {
    2530 CBC        3412 :                     found = true;
    2531 GIC        3412 :                     break;
    2532 ECB             :                 }
    2533                 :             }
    2534 GIC       58931 :             if (found)
    2535                 :             {
    2536                 :                 /*
    2537                 :                  * column is defined in the new table.  For PRIMARY KEY, we
    2538                 :                  * can apply the NOT NULL constraint cheaply here ... unless
    2539                 :                  * the column is marked is_from_type, in which case marking it
    2540                 :                  * here would be ineffective (see MergeAttributes).  Note that
    2541                 :                  * this isn't effective in ALTER TABLE either, unless the
    2542                 :                  * column is being added in the same command.
    2543                 :                  */
    2544            3412 :                 if (constraint->contype == CONSTR_PRIMARY &&
    2545 CBC        3138 :                     !column->is_from_type)
    2546                 :                 {
    2547            3125 :                     column->is_not_null = true;
    2548 ECB             :                 }
    2549                 :             }
    2550 CBC       55519 :             else if (SystemAttributeByName(key) != NULL)
    2551 ECB             :             {
    2552                 :                 /*
    2553                 :                  * column will be a system column in the new table, so accept
    2554                 :                  * it. System columns can't ever be null, so no need to worry
    2555                 :                  * about PRIMARY/NOT NULL constraint.
    2556                 :                  */
    2557 UIC           0 :                 found = true;
    2558 ECB             :             }
    2559 GIC       55519 :             else if (cxt->inhRelations)
    2560                 :             {
    2561 ECB             :                 /* try inherited tables */
    2562                 :                 ListCell   *inher;
    2563                 : 
    2564 GIC          30 :                 foreach(inher, cxt->inhRelations)
    2565 ECB             :                 {
    2566 GIC          30 :                     RangeVar   *inh = lfirst_node(RangeVar, inher);
    2567 ECB             :                     Relation    rel;
    2568                 :                     int         count;
    2569                 : 
    2570 GIC          30 :                     rel = table_openrv(inh, AccessShareLock);
    2571                 :                     /* check user requested inheritance from valid relkind */
    2572              30 :                     if (rel->rd_rel->relkind != RELKIND_RELATION &&
    2573 UIC           0 :                         rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
    2574               0 :                         rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
    2575 LBC           0 :                         ereport(ERROR,
    2576                 :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2577 ECB             :                                  errmsg("inherited relation \"%s\" is not a table or foreign table",
    2578                 :                                         inh->relname)));
    2579 CBC          30 :                     for (count = 0; count < rel->rd_att->natts; count++)
    2580                 :                     {
    2581 GIC          30 :                         Form_pg_attribute inhattr = TupleDescAttr(rel->rd_att,
    2582                 :                                                                   count);
    2583 CBC          30 :                         char       *inhname = NameStr(inhattr->attname);
    2584 ECB             : 
    2585 CBC          30 :                         if (inhattr->attisdropped)
    2586 UIC           0 :                             continue;
    2587 CBC          30 :                         if (strcmp(key, inhname) == 0)
    2588 ECB             :                         {
    2589 GIC          30 :                             found = true;
    2590              30 :                             break;
    2591                 :                         }
    2592 ECB             :                     }
    2593 GIC          30 :                     table_close(rel, NoLock);
    2594 CBC          30 :                     if (found)
    2595              30 :                         break;
    2596 ECB             :                 }
    2597                 :             }
    2598                 : 
    2599                 :             /*
    2600                 :              * In the ALTER TABLE case, don't complain about index keys not
    2601                 :              * created in the command; they may well exist already.
    2602                 :              * DefineIndex will complain about them if not.
    2603                 :              */
    2604 CBC       58931 :             if (!found && !cxt->isalter)
    2605 UIC           0 :                 ereport(ERROR,
    2606 ECB             :                         (errcode(ERRCODE_UNDEFINED_COLUMN),
    2607                 :                          errmsg("column \"%s\" named in key does not exist", key),
    2608                 :                          parser_errposition(cxt->pstate, constraint->location)));
    2609                 : 
    2610                 :             /* Check for PRIMARY KEY(foo, foo) */
    2611 GIC       89702 :             foreach(columns, index->indexParams)
    2612                 :             {
    2613           30771 :                 iparam = (IndexElem *) lfirst(columns);
    2614           30771 :                 if (iparam->name && strcmp(key, iparam->name) == 0)
    2615                 :                 {
    2616 UIC           0 :                     if (index->primary)
    2617               0 :                         ereport(ERROR,
    2618                 :                                 (errcode(ERRCODE_DUPLICATE_COLUMN),
    2619                 :                                  errmsg("column \"%s\" appears twice in primary key constraint",
    2620 ECB             :                                         key),
    2621                 :                                  parser_errposition(cxt->pstate, constraint->location)));
    2622                 :                     else
    2623 LBC           0 :                         ereport(ERROR,
    2624                 :                                 (errcode(ERRCODE_DUPLICATE_COLUMN),
    2625                 :                                  errmsg("column \"%s\" appears twice in unique constraint",
    2626 ECB             :                                         key),
    2627                 :                                  parser_errposition(cxt->pstate, constraint->location)));
    2628                 :                 }
    2629                 :             }
    2630                 : 
    2631                 :             /* OK, add it to the index definition */
    2632 GIC       58931 :             iparam = makeNode(IndexElem);
    2633 GBC       58931 :             iparam->name = pstrdup(key);
    2634 GIC       58931 :             iparam->expr = NULL;
    2635 CBC       58931 :             iparam->indexcolname = NULL;
    2636 GIC       58931 :             iparam->collation = NIL;
    2637           58931 :             iparam->opclass = NIL;
    2638           58931 :             iparam->opclassopts = NIL;
    2639           58931 :             iparam->ordering = SORTBY_DEFAULT;
    2640 CBC       58931 :             iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
    2641 GIC       58931 :             index->indexParams = lappend(index->indexParams, iparam);
    2642 ECB             : 
    2643 GNC       58931 :             if (constraint->contype == CONSTR_PRIMARY)
    2644 ECB             :             {
    2645 GBC       28454 :                 AlterTableCmd *notnullcmd = makeNode(AlterTableCmd);
    2646 EUB             : 
    2647 GNC       28454 :                 notnullcmd->subtype = AT_SetAttNotNull;
    2648 GIC       28454 :                 notnullcmd->name = pstrdup(key);
    2649           28454 :                 notnullcmds = lappend(notnullcmds, notnullcmd);
    2650                 :             }
    2651 ECB             :         }
    2652                 :     }
    2653                 : 
    2654                 :     /*
    2655                 :      * Add included columns to index definition.  This is much like the
    2656                 :      * simple-column-name-list code above, except that we don't worry about
    2657                 :      * NOT NULL marking; included columns in a primary key should not be
    2658 EUB             :      * forced NOT NULL.  We don't complain about duplicate columns, either,
    2659 ECB             :      * though maybe we should?
    2660                 :      */
    2661 CBC       37205 :     foreach(lc, constraint->including)
    2662 ECB             :     {
    2663 GIC         154 :         char       *key = strVal(lfirst(lc));
    2664             154 :         bool        found = false;
    2665 CBC         154 :         ColumnDef  *column = NULL;
    2666 ECB             :         ListCell   *columns;
    2667                 :         IndexElem  *iparam;
    2668                 : 
    2669 GIC         331 :         foreach(columns, cxt->columns)
    2670                 :         {
    2671             272 :             column = lfirst_node(ColumnDef, columns);
    2672             272 :             if (strcmp(column->colname, key) == 0)
    2673                 :             {
    2674              95 :                 found = true;
    2675              95 :                 break;
    2676 ECB             :             }
    2677 EUB             :         }
    2678                 : 
    2679 GIC         154 :         if (!found)
    2680                 :         {
    2681              59 :             if (SystemAttributeByName(key) != NULL)
    2682                 :             {
    2683 ECB             :                 /*
    2684                 :                  * column will be a system column in the new table, so accept
    2685                 :                  * it.
    2686                 :                  */
    2687 UIC           0 :                 found = true;
    2688 EUB             :             }
    2689 GBC          59 :             else if (cxt->inhRelations)
    2690                 :             {
    2691                 :                 /* try inherited tables */
    2692                 :                 ListCell   *inher;
    2693                 : 
    2694 UIC           0 :                 foreach(inher, cxt->inhRelations)
    2695 EUB             :                 {
    2696 UIC           0 :                     RangeVar   *inh = lfirst_node(RangeVar, inher);
    2697                 :                     Relation    rel;
    2698                 :                     int         count;
    2699                 : 
    2700               0 :                     rel = table_openrv(inh, AccessShareLock);
    2701                 :                     /* check user requested inheritance from valid relkind */
    2702               0 :                     if (rel->rd_rel->relkind != RELKIND_RELATION &&
    2703               0 :                         rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
    2704 LBC           0 :                         rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
    2705               0 :                         ereport(ERROR,
    2706 ECB             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2707                 :                                  errmsg("inherited relation \"%s\" is not a table or foreign table",
    2708                 :                                         inh->relname)));
    2709 LBC           0 :                     for (count = 0; count < rel->rd_att->natts; count++)
    2710 ECB             :                     {
    2711 LBC           0 :                         Form_pg_attribute inhattr = TupleDescAttr(rel->rd_att,
    2712 ECB             :                                                                   count);
    2713 LBC           0 :                         char       *inhname = NameStr(inhattr->attname);
    2714                 : 
    2715               0 :                         if (inhattr->attisdropped)
    2716 UIC           0 :                             continue;
    2717 LBC           0 :                         if (strcmp(key, inhname) == 0)
    2718                 :                         {
    2719               0 :                             found = true;
    2720               0 :                             break;
    2721 ECB             :                         }
    2722                 :                     }
    2723 UIC           0 :                     table_close(rel, NoLock);
    2724               0 :                     if (found)
    2725               0 :                         break;
    2726                 :                 }
    2727                 :             }
    2728                 :         }
    2729                 : 
    2730                 :         /*
    2731                 :          * In the ALTER TABLE case, don't complain about index keys not
    2732                 :          * created in the command; they may well exist already. DefineIndex
    2733 ECB             :          * will complain about them if not.
    2734                 :          */
    2735 CBC         154 :         if (!found && !cxt->isalter)
    2736 LBC           0 :             ereport(ERROR,
    2737 ECB             :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    2738                 :                      errmsg("column \"%s\" named in key does not exist", key),
    2739                 :                      parser_errposition(cxt->pstate, constraint->location)));
    2740                 : 
    2741                 :         /* OK, add it to the index definition */
    2742 GIC         154 :         iparam = makeNode(IndexElem);
    2743 CBC         154 :         iparam->name = pstrdup(key);
    2744             154 :         iparam->expr = NULL;
    2745 GIC         154 :         iparam->indexcolname = NULL;
    2746 CBC         154 :         iparam->collation = NIL;
    2747             154 :         iparam->opclass = NIL;
    2748 GIC         154 :         iparam->opclassopts = NIL;
    2749             154 :         index->indexIncludingParams = lappend(index->indexIncludingParams, iparam);
    2750                 :     }
    2751 ECB             : 
    2752                 :     /*
    2753                 :      * If we found anything that requires run-time SET NOT NULL, build a full
    2754                 :      * ALTER TABLE command for that and add it to cxt->alist.
    2755                 :      */
    2756 GIC       37051 :     if (notnullcmds)
    2757                 :     {
    2758           22076 :         AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
    2759 EUB             : 
    2760 GIC       22076 :         alterstmt->relation = copyObject(cxt->relation);
    2761 CBC       22076 :         alterstmt->cmds = notnullcmds;
    2762 GIC       22076 :         alterstmt->objtype = OBJECT_TABLE;
    2763           22076 :         alterstmt->missing_ok = false;
    2764                 : 
    2765           22076 :         cxt->alist = lappend(cxt->alist, alterstmt);
    2766 EUB             :     }
    2767                 : 
    2768 GBC       37051 :     return index;
    2769                 : }
    2770                 : 
    2771                 : /*
    2772 EUB             :  * transformExtendedStatistics
    2773                 :  *     Handle extended statistic objects
    2774                 :  *
    2775                 :  * Right now, there's nothing to do here, so we just append the list to
    2776                 :  * the existing "after" list.
    2777                 :  */
    2778                 : static void
    2779 GIC       55500 : transformExtendedStatistics(CreateStmtContext *cxt)
    2780                 : {
    2781 GBC       55500 :     cxt->alist = list_concat(cxt->alist, cxt->extstats);
    2782 GIC       55500 : }
    2783 EUB             : 
    2784                 : /*
    2785                 :  * transformCheckConstraints
    2786                 :  *      handle CHECK constraints
    2787                 :  *
    2788                 :  * Right now, there's nothing to do here when called from ALTER TABLE,
    2789                 :  * but the other constraint-transformation functions are called in both
    2790                 :  * the CREATE TABLE and ALTER TABLE paths, so do the same here, and just
    2791                 :  * don't do anything if we're not authorized to skip validation.
    2792                 :  */
    2793                 : static void
    2794 GIC       55500 : transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation)
    2795 EUB             : {
    2796                 :     ListCell   *ckclist;
    2797                 : 
    2798 GIC       55500 :     if (cxt->ckconstraints == NIL)
    2799           54844 :         return;
    2800                 : 
    2801                 :     /*
    2802                 :      * If creating a new table (but not a foreign table), we can safely skip
    2803                 :      * validation of check constraints, and nonetheless mark them valid. (This
    2804                 :      * will override any user-supplied NOT VALID flag.)
    2805                 :      */
    2806             656 :     if (skipValidation)
    2807 ECB             :     {
    2808 GBC         598 :         foreach(ckclist, cxt->ckconstraints)
    2809                 :         {
    2810 GIC         325 :             Constraint *constraint = (Constraint *) lfirst(ckclist);
    2811                 : 
    2812             325 :             constraint->skip_validation = true;
    2813             325 :             constraint->initially_valid = true;
    2814 ECB             :         }
    2815                 :     }
    2816                 : }
    2817                 : 
    2818                 : /*
    2819                 :  * transformFKConstraints
    2820                 :  *      handle FOREIGN KEY constraints
    2821                 :  */
    2822                 : static void
    2823 GIC       55500 : transformFKConstraints(CreateStmtContext *cxt,
    2824                 :                        bool skipValidation, bool isAddConstraint)
    2825                 : {
    2826                 :     ListCell   *fkclist;
    2827                 : 
    2828 CBC       55500 :     if (cxt->fkconstraints == NIL)
    2829 GIC       53931 :         return;
    2830 ECB             : 
    2831                 :     /*
    2832                 :      * If CREATE TABLE or adding a column with NULL default, we can safely
    2833                 :      * skip validation of FK constraints, and nonetheless mark them valid.
    2834                 :      * (This will override any user-supplied NOT VALID flag.)
    2835                 :      */
    2836 GIC        1569 :     if (skipValidation)
    2837 ECB             :     {
    2838 GIC        1109 :         foreach(fkclist, cxt->fkconstraints)
    2839                 :         {
    2840 CBC         570 :             Constraint *constraint = (Constraint *) lfirst(fkclist);
    2841                 : 
    2842 GIC         570 :             constraint->skip_validation = true;
    2843             570 :             constraint->initially_valid = true;
    2844                 :         }
    2845                 :     }
    2846                 : 
    2847                 :     /*
    2848                 :      * For CREATE TABLE or ALTER TABLE ADD COLUMN, gin up an ALTER TABLE ADD
    2849                 :      * CONSTRAINT command to execute after the basic command is complete. (If
    2850                 :      * called from ADD CONSTRAINT, that routine will add the FK constraints to
    2851 ECB             :      * its own subcommand list.)
    2852                 :      *
    2853                 :      * Note: the ADD CONSTRAINT command must also execute after any index
    2854                 :      * creation commands.  Thus, this should run after
    2855                 :      * transformIndexConstraints, so that the CREATE INDEX commands are
    2856                 :      * already in cxt->alist.  See also the handling of cxt->likeclauses.
    2857                 :      */
    2858 GIC        1569 :     if (!isAddConstraint)
    2859                 :     {
    2860             536 :         AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
    2861                 : 
    2862             536 :         alterstmt->relation = cxt->relation;
    2863             536 :         alterstmt->cmds = NIL;
    2864             536 :         alterstmt->objtype = OBJECT_TABLE;
    2865                 : 
    2866 CBC        1103 :         foreach(fkclist, cxt->fkconstraints)
    2867                 :         {
    2868 GIC         567 :             Constraint *constraint = (Constraint *) lfirst(fkclist);
    2869             567 :             AlterTableCmd *altercmd = makeNode(AlterTableCmd);
    2870 ECB             : 
    2871 CBC         567 :             altercmd->subtype = AT_AddConstraint;
    2872 GIC         567 :             altercmd->name = NULL;
    2873             567 :             altercmd->def = (Node *) constraint;
    2874             567 :             alterstmt->cmds = lappend(alterstmt->cmds, altercmd);
    2875                 :         }
    2876                 : 
    2877             536 :         cxt->alist = lappend(cxt->alist, alterstmt);
    2878 ECB             :     }
    2879                 : }
    2880                 : 
    2881                 : /*
    2882                 :  * transformIndexStmt - parse analysis for CREATE INDEX and ALTER TABLE
    2883                 :  *
    2884                 :  * Note: this is a no-op for an index not using either index expressions or
    2885                 :  * a predicate expression.  There are several code paths that create indexes
    2886                 :  * without bothering to call this, because they know they don't have any
    2887                 :  * such expressions to deal with.
    2888                 :  *
    2889                 :  * To avoid race conditions, it's important that this function rely only on
    2890                 :  * the passed-in relid (and not on stmt->relation) to determine the target
    2891                 :  * relation.
    2892                 :  */
    2893                 : IndexStmt *
    2894 GIC       39881 : transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
    2895 ECB             : {
    2896                 :     ParseState *pstate;
    2897                 :     ParseNamespaceItem *nsitem;
    2898                 :     ListCell   *l;
    2899                 :     Relation    rel;
    2900                 : 
    2901                 :     /* Nothing to do if statement already transformed. */
    2902 GIC       39881 :     if (stmt->transformed)
    2903              56 :         return stmt;
    2904                 : 
    2905                 :     /* Set up pstate */
    2906           39825 :     pstate = make_parsestate(NULL);
    2907           39825 :     pstate->p_sourcetext = queryString;
    2908 ECB             : 
    2909                 :     /*
    2910                 :      * Put the parent table into the rtable so that the expressions can refer
    2911                 :      * to its fields without qualification.  Caller is responsible for locking
    2912                 :      * relation, but we still need to open it.
    2913                 :      */
    2914 CBC       39825 :     rel = relation_open(relid, NoLock);
    2915           39825 :     nsitem = addRangeTableEntryForRelation(pstate, rel,
    2916                 :                                            AccessShareLock,
    2917                 :                                            NULL, false, true);
    2918                 : 
    2919                 :     /* no to join list, yes to namespaces */
    2920 GIC       39825 :     addNSItemToQuery(pstate, nsitem, false, true, true);
    2921                 : 
    2922                 :     /* take care of the where clause */
    2923           39825 :     if (stmt->whereClause)
    2924                 :     {
    2925             175 :         stmt->whereClause = transformWhereClause(pstate,
    2926                 :                                                  stmt->whereClause,
    2927                 :                                                  EXPR_KIND_INDEX_PREDICATE,
    2928                 :                                                  "WHERE");
    2929                 :         /* we have to fix its collations too */
    2930 CBC         175 :         assign_expr_collations(pstate, stmt->whereClause);
    2931                 :     }
    2932 ECB             : 
    2933                 :     /* take care of any index expressions */
    2934 CBC      102372 :     foreach(l, stmt->indexParams)
    2935 ECB             :     {
    2936 CBC       62556 :         IndexElem  *ielem = (IndexElem *) lfirst(l);
    2937                 : 
    2938           62556 :         if (ielem->expr)
    2939                 :         {
    2940 ECB             :             /* Extract preliminary index col name before transforming expr */
    2941 CBC         306 :             if (ielem->indexcolname == NULL)
    2942 GIC         306 :                 ielem->indexcolname = FigureIndexColname(ielem->expr);
    2943 ECB             : 
    2944                 :             /* Now do parse transformation of the expression */
    2945 CBC         306 :             ielem->expr = transformExpr(pstate, ielem->expr,
    2946 ECB             :                                         EXPR_KIND_INDEX_EXPRESSION);
    2947                 : 
    2948                 :             /* We have to fix its collations too */
    2949 CBC         297 :             assign_expr_collations(pstate, ielem->expr);
    2950                 : 
    2951                 :             /*
    2952                 :              * transformExpr() should have already rejected subqueries,
    2953                 :              * aggregates, window functions, and SRFs, based on the EXPR_KIND_
    2954                 :              * for an index expression.
    2955                 :              *
    2956                 :              * DefineIndex() will make more checks.
    2957                 :              */
    2958                 :         }
    2959                 :     }
    2960                 : 
    2961                 :     /*
    2962                 :      * Check that only the base rel is mentioned.  (This should be dead code
    2963                 :      * now that add_missing_from is history.)
    2964                 :      */
    2965 GIC       39816 :     if (list_length(pstate->p_rtable) != 1)
    2966 LBC           0 :         ereport(ERROR,
    2967                 :                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    2968                 :                  errmsg("index expressions and predicates can refer only to the table being indexed")));
    2969                 : 
    2970 GIC       39816 :     free_parsestate(pstate);
    2971                 : 
    2972                 :     /* Close relation */
    2973           39816 :     table_close(rel, NoLock);
    2974 ECB             : 
    2975                 :     /* Mark statement as successfully transformed */
    2976 GIC       39816 :     stmt->transformed = true;
    2977                 : 
    2978 CBC       39816 :     return stmt;
    2979 ECB             : }
    2980                 : 
    2981                 : /*
    2982                 :  * transformStatsStmt - parse analysis for CREATE STATISTICS
    2983                 :  *
    2984                 :  * To avoid race conditions, it's important that this function relies only on
    2985                 :  * the passed-in relid (and not on stmt->relation) to determine the target
    2986                 :  * relation.
    2987                 :  */
    2988                 : CreateStatsStmt *
    2989 GIC         295 : transformStatsStmt(Oid relid, CreateStatsStmt *stmt, const char *queryString)
    2990                 : {
    2991                 :     ParseState *pstate;
    2992 ECB             :     ParseNamespaceItem *nsitem;
    2993                 :     ListCell   *l;
    2994                 :     Relation    rel;
    2995                 : 
    2996                 :     /* Nothing to do if statement already transformed. */
    2997 CBC         295 :     if (stmt->transformed)
    2998 GIC          18 :         return stmt;
    2999                 : 
    3000                 :     /* Set up pstate */
    3001             277 :     pstate = make_parsestate(NULL);
    3002 CBC         277 :     pstate->p_sourcetext = queryString;
    3003                 : 
    3004                 :     /*
    3005                 :      * Put the parent table into the rtable so that the expressions can refer
    3006 ECB             :      * to its fields without qualification.  Caller is responsible for locking
    3007                 :      * relation, but we still need to open it.
    3008                 :      */
    3009 GIC         277 :     rel = relation_open(relid, NoLock);
    3010 CBC         277 :     nsitem = addRangeTableEntryForRelation(pstate, rel,
    3011                 :                                            AccessShareLock,
    3012                 :                                            NULL, false, true);
    3013 ECB             : 
    3014                 :     /* no to join list, yes to namespaces */
    3015 GIC         277 :     addNSItemToQuery(pstate, nsitem, false, true, true);
    3016                 : 
    3017 ECB             :     /* take care of any expressions */
    3018 GIC        1009 :     foreach(l, stmt->exprs)
    3019                 :     {
    3020             732 :         StatsElem  *selem = (StatsElem *) lfirst(l);
    3021 ECB             : 
    3022 GIC         732 :         if (selem->expr)
    3023                 :         {
    3024                 :             /* Now do parse transformation of the expression */
    3025             216 :             selem->expr = transformExpr(pstate, selem->expr,
    3026                 :                                         EXPR_KIND_STATS_EXPRESSION);
    3027                 : 
    3028                 :             /* We have to fix its collations too */
    3029             216 :             assign_expr_collations(pstate, selem->expr);
    3030                 :         }
    3031                 :     }
    3032                 : 
    3033                 :     /*
    3034                 :      * Check that only the base rel is mentioned.  (This should be dead code
    3035                 :      * now that add_missing_from is history.)
    3036                 :      */
    3037 CBC         277 :     if (list_length(pstate->p_rtable) != 1)
    3038 UBC           0 :         ereport(ERROR,
    3039                 :                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    3040                 :                  errmsg("statistics expressions can refer only to the table being referenced")));
    3041                 : 
    3042 CBC         277 :     free_parsestate(pstate);
    3043                 : 
    3044                 :     /* Close relation */
    3045             277 :     table_close(rel, NoLock);
    3046                 : 
    3047                 :     /* Mark statement as successfully transformed */
    3048             277 :     stmt->transformed = true;
    3049                 : 
    3050             277 :     return stmt;
    3051                 : }
    3052                 : 
    3053                 : 
    3054                 : /*
    3055                 :  * transformRuleStmt -
    3056                 :  *    transform a CREATE RULE Statement. The action is a list of parse
    3057                 :  *    trees which is transformed into a list of query trees, and we also
    3058                 :  *    transform the WHERE clause if any.
    3059                 :  *
    3060                 :  * actions and whereClause are output parameters that receive the
    3061 ECB             :  * transformed results.
    3062                 :  */
    3063                 : void
    3064 GIC        1031 : transformRuleStmt(RuleStmt *stmt, const char *queryString,
    3065                 :                   List **actions, Node **whereClause)
    3066                 : {
    3067                 :     Relation    rel;
    3068                 :     ParseState *pstate;
    3069 ECB             :     ParseNamespaceItem *oldnsitem;
    3070                 :     ParseNamespaceItem *newnsitem;
    3071                 : 
    3072                 :     /*
    3073                 :      * To avoid deadlock, make sure the first thing we do is grab
    3074                 :      * AccessExclusiveLock on the target relation.  This will be needed by
    3075                 :      * DefineQueryRewrite(), and we don't want to grab a lesser lock
    3076                 :      * beforehand.
    3077                 :      */
    3078 GIC        1031 :     rel = table_openrv(stmt->relation, AccessExclusiveLock);
    3079                 : 
    3080            1031 :     if (rel->rd_rel->relkind == RELKIND_MATVIEW)
    3081 LBC           0 :         ereport(ERROR,
    3082 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3083                 :                  errmsg("rules on materialized views are not supported")));
    3084                 : 
    3085                 :     /* Set up pstate */
    3086 GIC        1031 :     pstate = make_parsestate(NULL);
    3087 CBC        1031 :     pstate->p_sourcetext = queryString;
    3088                 : 
    3089                 :     /*
    3090 ECB             :      * NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' equal to 2.
    3091                 :      * Set up their ParseNamespaceItems in the main pstate for use in parsing
    3092                 :      * the rule qualification.
    3093                 :      */
    3094 CBC        1031 :     oldnsitem = addRangeTableEntryForRelation(pstate, rel,
    3095                 :                                               AccessShareLock,
    3096                 :                                               makeAlias("old", NIL),
    3097 ECB             :                                               false, false);
    3098 GIC        1031 :     newnsitem = addRangeTableEntryForRelation(pstate, rel,
    3099                 :                                               AccessShareLock,
    3100                 :                                               makeAlias("new", NIL),
    3101 ECB             :                                               false, false);
    3102                 : 
    3103                 :     /*
    3104                 :      * They must be in the namespace too for lookup purposes, but only add the
    3105                 :      * one(s) that are relevant for the current kind of rule.  In an UPDATE
    3106                 :      * rule, quals must refer to OLD.field or NEW.field to be unambiguous, but
    3107 EUB             :      * there's no need to be so picky for INSERT & DELETE.  We do not add them
    3108                 :      * to the joinlist.
    3109                 :      */
    3110 GIC        1031 :     switch (stmt->event)
    3111 ECB             :     {
    3112 GIC           9 :         case CMD_SELECT:
    3113               9 :             addNSItemToQuery(pstate, oldnsitem, false, true, true);
    3114 CBC           9 :             break;
    3115 GIC         719 :         case CMD_UPDATE:
    3116             719 :             addNSItemToQuery(pstate, oldnsitem, false, true, true);
    3117 CBC         719 :             addNSItemToQuery(pstate, newnsitem, false, true, true);
    3118 GIC         719 :             break;
    3119 CBC         227 :         case CMD_INSERT:
    3120 GIC         227 :             addNSItemToQuery(pstate, newnsitem, false, true, true);
    3121             227 :             break;
    3122              76 :         case CMD_DELETE:
    3123              76 :             addNSItemToQuery(pstate, oldnsitem, false, true, true);
    3124              76 :             break;
    3125 UIC           0 :         default:
    3126               0 :             elog(ERROR, "unrecognized event type: %d",
    3127                 :                  (int) stmt->event);
    3128                 :             break;
    3129                 :     }
    3130                 : 
    3131                 :     /* take care of the where clause */
    3132 GIC        1031 :     *whereClause = transformWhereClause(pstate,
    3133 ECB             :                                         stmt->whereClause,
    3134                 :                                         EXPR_KIND_WHERE,
    3135                 :                                         "WHERE");
    3136                 :     /* we have to fix its collations too */
    3137 GIC        1031 :     assign_expr_collations(pstate, *whereClause);
    3138                 : 
    3139                 :     /* this is probably dead code without add_missing_from: */
    3140            1031 :     if (list_length(pstate->p_rtable) != 2) /* naughty, naughty... */
    3141 UIC           0 :         ereport(ERROR,
    3142                 :                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    3143                 :                  errmsg("rule WHERE condition cannot contain references to other relations")));
    3144                 : 
    3145                 :     /*
    3146                 :      * 'instead nothing' rules with a qualification need a query rangetable so
    3147 ECB             :      * the rewrite handler can add the negated rule qualification to the
    3148                 :      * original query. We create a query with the new command type CMD_NOTHING
    3149                 :      * here that is treated specially by the rewrite system.
    3150 EUB             :      */
    3151 GIC        1031 :     if (stmt->actions == NIL)
    3152                 :     {
    3153             336 :         Query      *nothing_qry = makeNode(Query);
    3154                 : 
    3155 CBC         336 :         nothing_qry->commandType = CMD_NOTHING;
    3156             336 :         nothing_qry->rtable = pstate->p_rtable;
    3157 GNC         336 :         nothing_qry->rteperminfos = pstate->p_rteperminfos;
    3158 GIC         336 :         nothing_qry->jointree = makeFromExpr(NIL, NULL); /* no join wanted */
    3159                 : 
    3160             336 :         *actions = list_make1(nothing_qry);
    3161                 :     }
    3162                 :     else
    3163                 :     {
    3164 ECB             :         ListCell   *l;
    3165 GIC         695 :         List       *newactions = NIL;
    3166                 : 
    3167                 :         /*
    3168 ECB             :          * transform each statement, like parse_sub_analyze()
    3169                 :          */
    3170 GIC        1404 :         foreach(l, stmt->actions)
    3171                 :         {
    3172             718 :             Node       *action = (Node *) lfirst(l);
    3173             718 :             ParseState *sub_pstate = make_parsestate(NULL);
    3174                 :             Query      *sub_qry,
    3175                 :                        *top_subqry;
    3176                 :             bool        has_old,
    3177                 :                         has_new;
    3178                 : 
    3179                 :             /*
    3180 ECB             :              * Since outer ParseState isn't parent of inner, have to pass down
    3181                 :              * the query text by hand.
    3182                 :              */
    3183 CBC         718 :             sub_pstate->p_sourcetext = queryString;
    3184 ECB             : 
    3185                 :             /*
    3186                 :              * Set up OLD/NEW in the rtable for this statement.  The entries
    3187                 :              * are added only to relnamespace, not varnamespace, because we
    3188                 :              * don't want them to be referred to by unqualified field names
    3189                 :              * nor "*" in the rule actions.  We decide later whether to put
    3190                 :              * them in the joinlist.
    3191                 :              */
    3192 CBC         718 :             oldnsitem = addRangeTableEntryForRelation(sub_pstate, rel,
    3193 ECB             :                                                       AccessShareLock,
    3194                 :                                                       makeAlias("old", NIL),
    3195 EUB             :                                                       false, false);
    3196 GBC         718 :             newnsitem = addRangeTableEntryForRelation(sub_pstate, rel,
    3197                 :                                                       AccessShareLock,
    3198                 :                                                       makeAlias("new", NIL),
    3199                 :                                                       false, false);
    3200 CBC         718 :             addNSItemToQuery(sub_pstate, oldnsitem, false, true, false);
    3201 GIC         718 :             addNSItemToQuery(sub_pstate, newnsitem, false, true, false);
    3202                 : 
    3203                 :             /* Transform the rule action statement */
    3204             718 :             top_subqry = transformStmt(sub_pstate, action);
    3205 ECB             : 
    3206                 :             /*
    3207                 :              * We cannot support utility-statement actions (eg NOTIFY) with
    3208                 :              * nonempty rule WHERE conditions, because there's no way to make
    3209 EUB             :              * the utility action execute conditionally.
    3210                 :              */
    3211 GIC         712 :             if (top_subqry->commandType == CMD_UTILITY &&
    3212              16 :                 *whereClause != NULL)
    3213 UIC           0 :                 ereport(ERROR,
    3214                 :                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    3215                 :                          errmsg("rules with WHERE conditions can only have SELECT, INSERT, UPDATE, or DELETE actions")));
    3216                 : 
    3217                 :             /*
    3218                 :              * If the action is INSERT...SELECT, OLD/NEW have been pushed down
    3219 ECB             :              * into the SELECT, and that's what we need to look at. (Ugly
    3220                 :              * kluge ... try to fix this when we redesign querytrees.)
    3221                 :              */
    3222 GIC         712 :             sub_qry = getInsertSelectQuery(top_subqry, NULL);
    3223 ECB             : 
    3224                 :             /*
    3225                 :              * If the sub_qry is a setop, we cannot attach any qualifications
    3226                 :              * to it, because the planner won't notice them.  This could
    3227                 :              * perhaps be relaxed someday, but for now, we may as well reject
    3228                 :              * such a rule immediately.
    3229                 :              */
    3230 GIC         712 :             if (sub_qry->setOperations != NULL && *whereClause != NULL)
    3231 UIC           0 :                 ereport(ERROR,
    3232                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3233 ECB             :                          errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
    3234                 : 
    3235                 :             /*
    3236                 :              * Validate action's use of OLD/NEW, qual too
    3237                 :              */
    3238 CBC         712 :             has_old =
    3239 GIC         987 :                 rangeTableEntry_used((Node *) sub_qry, PRS2_OLD_VARNO, 0) ||
    3240 CBC         275 :                 rangeTableEntry_used(*whereClause, PRS2_OLD_VARNO, 0);
    3241             712 :             has_new =
    3242 GIC         863 :                 rangeTableEntry_used((Node *) sub_qry, PRS2_NEW_VARNO, 0) ||
    3243             151 :                 rangeTableEntry_used(*whereClause, PRS2_NEW_VARNO, 0);
    3244                 : 
    3245             712 :             switch (stmt->event)
    3246                 :             {
    3247               9 :                 case CMD_SELECT:
    3248               9 :                     if (has_old)
    3249 UIC           0 :                         ereport(ERROR,
    3250                 :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    3251 ECB             :                                  errmsg("ON SELECT rule cannot use OLD")));
    3252 GIC           9 :                     if (has_new)
    3253 UIC           0 :                         ereport(ERROR,
    3254                 :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    3255                 :                                  errmsg("ON SELECT rule cannot use NEW")));
    3256 GIC           9 :                     break;
    3257             420 :                 case CMD_UPDATE:
    3258                 :                     /* both are OK */
    3259             420 :                     break;
    3260 CBC         205 :                 case CMD_INSERT:
    3261 GIC         205 :                     if (has_old)
    3262 UIC           0 :                         ereport(ERROR,
    3263                 :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    3264 ECB             :                                  errmsg("ON INSERT rule cannot use OLD")));
    3265 GIC         205 :                     break;
    3266              78 :                 case CMD_DELETE:
    3267              78 :                     if (has_new)
    3268 LBC           0 :                         ereport(ERROR,
    3269 ECB             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    3270                 :                                  errmsg("ON DELETE rule cannot use NEW")));
    3271 GIC          78 :                     break;
    3272 LBC           0 :                 default:
    3273 UIC           0 :                     elog(ERROR, "unrecognized event type: %d",
    3274                 :                          (int) stmt->event);
    3275                 :                     break;
    3276                 :             }
    3277                 : 
    3278                 :             /*
    3279 ECB             :              * OLD/NEW are not allowed in WITH queries, because they would
    3280                 :              * amount to outer references for the WITH, which we disallow.
    3281 EUB             :              * However, they were already in the outer rangetable when we
    3282                 :              * analyzed the query, so we have to check.
    3283                 :              *
    3284                 :              * Note that in the INSERT...SELECT case, we need to examine the
    3285                 :              * CTE lists of both top_subqry and sub_qry.
    3286                 :              *
    3287                 :              * Note that we aren't digging into the body of the query looking
    3288                 :              * for WITHs in nested sub-SELECTs.  A WITH down there can
    3289                 :              * legitimately refer to OLD/NEW, because it'd be an
    3290 ECB             :              * indirect-correlated outer reference.
    3291                 :              */
    3292 GIC         712 :             if (rangeTableEntry_used((Node *) top_subqry->cteList,
    3293             709 :                                      PRS2_OLD_VARNO, 0) ||
    3294             709 :                 rangeTableEntry_used((Node *) sub_qry->cteList,
    3295                 :                                      PRS2_OLD_VARNO, 0))
    3296               3 :                 ereport(ERROR,
    3297                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3298 ECB             :                          errmsg("cannot refer to OLD within WITH query")));
    3299 GBC         709 :             if (rangeTableEntry_used((Node *) top_subqry->cteList,
    3300 GIC         709 :                                      PRS2_NEW_VARNO, 0) ||
    3301             709 :                 rangeTableEntry_used((Node *) sub_qry->cteList,
    3302                 :                                      PRS2_NEW_VARNO, 0))
    3303 UIC           0 :                 ereport(ERROR,
    3304                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3305                 :                          errmsg("cannot refer to NEW within WITH query")));
    3306 ECB             : 
    3307                 :             /*
    3308                 :              * For efficiency's sake, add OLD to the rule action's jointree
    3309                 :              * only if it was actually referenced in the statement or qual.
    3310                 :              *
    3311                 :              * For INSERT, NEW is not really a relation (only a reference to
    3312                 :              * the to-be-inserted tuple) and should never be added to the
    3313                 :              * jointree.
    3314                 :              *
    3315                 :              * For UPDATE, we treat NEW as being another kind of reference to
    3316                 :              * OLD, because it represents references to *transformed* tuples
    3317 EUB             :              * of the existing relation.  It would be wrong to enter NEW
    3318                 :              * separately in the jointree, since that would cause a double
    3319                 :              * join of the updated relation.  It's also wrong to fail to make
    3320 ECB             :              * a jointree entry if only NEW and not OLD is mentioned.
    3321 EUB             :              */
    3322 GIC         709 :             if (has_old || (has_new && stmt->event == CMD_UPDATE))
    3323                 :             {
    3324 ECB             :                 RangeTblRef *rtr;
    3325                 : 
    3326                 :                 /*
    3327                 :                  * If sub_qry is a setop, manipulating its jointree will do no
    3328                 :                  * good at all, because the jointree is dummy. (This should be
    3329                 :                  * a can't-happen case because of prior tests.)
    3330 EUB             :                  */
    3331 GIC         458 :                 if (sub_qry->setOperations != NULL)
    3332 UIC           0 :                     ereport(ERROR,
    3333 ECB             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3334                 :                              errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
    3335                 :                 /* hackishly add OLD to the already-built FROM clause */
    3336 GBC         458 :                 rtr = makeNode(RangeTblRef);
    3337 GIC         458 :                 rtr->rtindex = oldnsitem->p_rtindex;
    3338             458 :                 sub_qry->jointree->fromlist =
    3339 CBC         458 :                     lappend(sub_qry->jointree->fromlist, rtr);
    3340 EUB             :             }
    3341                 : 
    3342 GIC         709 :             newactions = lappend(newactions, top_subqry);
    3343                 : 
    3344             709 :             free_parsestate(sub_pstate);
    3345                 :         }
    3346                 : 
    3347             686 :         *actions = newactions;
    3348                 :     }
    3349                 : 
    3350            1022 :     free_parsestate(pstate);
    3351                 : 
    3352                 :     /* Close relation, but keep the exclusive lock */
    3353            1022 :     table_close(rel, NoLock);
    3354            1022 : }
    3355                 : 
    3356                 : 
    3357                 : /*
    3358                 :  * transformAlterTableStmt -
    3359                 :  *      parse analysis for ALTER TABLE
    3360 ECB             :  *
    3361                 :  * Returns the transformed AlterTableStmt.  There may be additional actions
    3362                 :  * to be done before and after the transformed statement, which are returned
    3363                 :  * in *beforeStmts and *afterStmts as lists of utility command parsetrees.
    3364                 :  *
    3365                 :  * To avoid race conditions, it's important that this function rely only on
    3366                 :  * the passed-in relid (and not on stmt->relation) to determine the target
    3367                 :  * relation.
    3368                 :  */
    3369                 : AlterTableStmt *
    3370 GIC       38378 : transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
    3371 EUB             :                         const char *queryString,
    3372                 :                         List **beforeStmts, List **afterStmts)
    3373                 : {
    3374                 :     Relation    rel;
    3375                 :     TupleDesc   tupdesc;
    3376                 :     ParseState *pstate;
    3377                 :     CreateStmtContext cxt;
    3378                 :     List       *save_alist;
    3379                 :     ListCell   *lcmd,
    3380                 :                *l;
    3381 GIC       38378 :     List       *newcmds = NIL;
    3382           38378 :     bool        skipValidation = true;
    3383                 :     AlterTableCmd *newcmd;
    3384                 :     ParseNamespaceItem *nsitem;
    3385                 : 
    3386                 :     /* Caller is responsible for locking the relation */
    3387           38378 :     rel = relation_open(relid, NoLock);
    3388           38378 :     tupdesc = RelationGetDescr(rel);
    3389                 : 
    3390 ECB             :     /* Set up pstate */
    3391 GIC       38378 :     pstate = make_parsestate(NULL);
    3392           38378 :     pstate->p_sourcetext = queryString;
    3393           38378 :     nsitem = addRangeTableEntryForRelation(pstate,
    3394                 :                                            rel,
    3395                 :                                            AccessShareLock,
    3396                 :                                            NULL,
    3397                 :                                            false,
    3398                 :                                            true);
    3399 CBC       38378 :     addNSItemToQuery(pstate, nsitem, false, true, true);
    3400 EUB             : 
    3401                 :     /* Set up CreateStmtContext */
    3402 GIC       38378 :     cxt.pstate = pstate;
    3403           38378 :     if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
    3404 ECB             :     {
    3405 CBC          81 :         cxt.stmtType = "ALTER FOREIGN TABLE";
    3406              81 :         cxt.isforeign = true;
    3407 ECB             :     }
    3408                 :     else
    3409                 :     {
    3410 CBC       38297 :         cxt.stmtType = "ALTER TABLE";
    3411 GIC       38297 :         cxt.isforeign = false;
    3412 ECB             :     }
    3413 GIC       38378 :     cxt.relation = stmt->relation;
    3414           38378 :     cxt.rel = rel;
    3415 CBC       38378 :     cxt.inhRelations = NIL;
    3416 GIC       38378 :     cxt.isalter = true;
    3417           38378 :     cxt.columns = NIL;
    3418 CBC       38378 :     cxt.ckconstraints = NIL;
    3419 GNC       38378 :     cxt.nnconstraints = NIL;
    3420 GIC       38378 :     cxt.fkconstraints = NIL;
    3421           38378 :     cxt.ixconstraints = NIL;
    3422 CBC       38378 :     cxt.likeclauses = NIL;
    3423           38378 :     cxt.extstats = NIL;
    3424 GIC       38378 :     cxt.blist = NIL;
    3425           38378 :     cxt.alist = NIL;
    3426           38378 :     cxt.pkey = NULL;
    3427           38378 :     cxt.ispartitioned = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
    3428           38378 :     cxt.partbound = NULL;
    3429           38378 :     cxt.ofType = false;
    3430                 : 
    3431                 :     /*
    3432                 :      * Transform ALTER subcommands that need it (most don't).  These largely
    3433                 :      * re-use code from CREATE TABLE.
    3434                 :      */
    3435           76729 :     foreach(lcmd, stmt->cmds)
    3436                 :     {
    3437           38378 :         AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
    3438                 : 
    3439 CBC       38378 :         switch (cmd->subtype)
    3440                 :         {
    3441 GIC         854 :             case AT_AddColumn:
    3442                 :                 {
    3443             854 :                     ColumnDef  *def = castNode(ColumnDef, cmd->def);
    3444                 : 
    3445             854 :                     transformColumnDefinition(&cxt, def);
    3446                 : 
    3447                 :                     /*
    3448                 :                      * If the column has a non-null default, we can't skip
    3449 ECB             :                      * validation of foreign keys.
    3450                 :                      */
    3451 GIC         854 :                     if (def->raw_default != NULL)
    3452             318 :                         skipValidation = false;
    3453                 : 
    3454                 :                     /*
    3455 ECB             :                      * All constraints are processed in other ways. Remove the
    3456                 :                      * original list
    3457                 :                      */
    3458 GIC         854 :                     def->constraints = NIL;
    3459 ECB             : 
    3460 CBC         854 :                     newcmds = lappend(newcmds, cmd);
    3461             854 :                     break;
    3462                 :                 }
    3463                 : 
    3464 GIC       35411 :             case AT_AddConstraint:
    3465                 : 
    3466 ECB             :                 /*
    3467                 :                  * The original AddConstraint cmd node doesn't go to newcmds
    3468                 :                  */
    3469 CBC       35411 :                 if (IsA(cmd->def, Constraint))
    3470 ECB             :                 {
    3471 GIC       35411 :                     transformTableConstraint(&cxt, (Constraint *) cmd->def);
    3472 CBC       35402 :                     if (((Constraint *) cmd->def)->contype == CONSTR_FOREIGN)
    3473            1030 :                         skipValidation = false;
    3474                 :                 }
    3475                 :                 else
    3476 UIC           0 :                     elog(ERROR, "unrecognized node type: %d",
    3477 ECB             :                          (int) nodeTag(cmd->def));
    3478 CBC       35402 :                 break;
    3479                 : 
    3480             553 :             case AT_AlterColumnType:
    3481 ECB             :                 {
    3482 CBC         553 :                     ColumnDef  *def = castNode(ColumnDef, cmd->def);
    3483 ECB             :                     AttrNumber  attnum;
    3484                 : 
    3485                 :                     /*
    3486                 :                      * For ALTER COLUMN TYPE, transform the USING clause if
    3487                 :                      * one was specified.
    3488                 :                      */
    3489 CBC         553 :                     if (def->raw_default)
    3490 ECB             :                     {
    3491 CBC         108 :                         def->cooked_default =
    3492             108 :                             transformExpr(pstate, def->raw_default,
    3493 ECB             :                                           EXPR_KIND_ALTER_COL_TRANSFORM);
    3494                 :                     }
    3495                 : 
    3496                 :                     /*
    3497                 :                      * For identity column, create ALTER SEQUENCE command to
    3498                 :                      * change the data type of the sequence.
    3499                 :                      */
    3500 GIC         553 :                     attnum = get_attnum(relid, cmd->name);
    3501             553 :                     if (attnum == InvalidAttrNumber)
    3502 LBC           0 :                         ereport(ERROR,
    3503                 :                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
    3504 ECB             :                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
    3505                 :                                         cmd->name, RelationGetRelationName(rel))));
    3506                 : 
    3507 GIC         553 :                     if (attnum > 0 &&
    3508 CBC         553 :                         TupleDescAttr(tupdesc, attnum - 1)->attidentity)
    3509                 :                     {
    3510              15 :                         Oid         seq_relid = getIdentitySequence(relid, attnum, false);
    3511 GIC          15 :                         Oid         typeOid = typenameTypeId(pstate, def->typeName);
    3512 CBC          15 :                         AlterSeqStmt *altseqstmt = makeNode(AlterSeqStmt);
    3513                 : 
    3514 GIC          15 :                         altseqstmt->sequence = makeRangeVar(get_namespace_name(get_rel_namespace(seq_relid)),
    3515                 :                                                             get_rel_name(seq_relid),
    3516                 :                                                             -1);
    3517              15 :                         altseqstmt->options = list_make1(makeDefElem("as", (Node *) makeTypeNameFromOid(typeOid, -1), -1));
    3518 CBC          15 :                         altseqstmt->for_identity = true;
    3519              15 :                         cxt.blist = lappend(cxt.blist, altseqstmt);
    3520                 :                     }
    3521                 : 
    3522 GIC         553 :                     newcmds = lappend(newcmds, cmd);
    3523             553 :                     break;
    3524                 :                 }
    3525 ECB             : 
    3526 GIC          51 :             case AT_AddIdentity:
    3527 ECB             :                 {
    3528 CBC          51 :                     Constraint *def = castNode(Constraint, cmd->def);
    3529 GIC          51 :                     ColumnDef  *newdef = makeNode(ColumnDef);
    3530                 :                     AttrNumber  attnum;
    3531 ECB             : 
    3532 GIC          51 :                     newdef->colname = cmd->name;
    3533              51 :                     newdef->identity = def->generated_when;
    3534              51 :                     cmd->def = (Node *) newdef;
    3535                 : 
    3536 CBC          51 :                     attnum = get_attnum(relid, cmd->name);
    3537 GIC          51 :                     if (attnum == InvalidAttrNumber)
    3538 LBC           0 :                         ereport(ERROR,
    3539 ECB             :                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
    3540                 :                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
    3541                 :                                         cmd->name, RelationGetRelationName(rel))));
    3542                 : 
    3543 GBC          51 :                     generateSerialExtraStmts(&cxt, newdef,
    3544                 :                                              get_atttype(relid, attnum),
    3545 ECB             :                                              def->options, true, true,
    3546                 :                                              NULL, NULL);
    3547                 : 
    3548 GIC          51 :                     newcmds = lappend(newcmds, cmd);
    3549 CBC          51 :                     break;
    3550                 :                 }
    3551                 : 
    3552 GIC          19 :             case AT_SetIdentity:
    3553                 :                 {
    3554                 :                     /*
    3555                 :                      * Create an ALTER SEQUENCE statement for the internal
    3556 ECB             :                      * sequence of the identity column.
    3557                 :                      */
    3558                 :                     ListCell   *lc;
    3559 CBC          19 :                     List       *newseqopts = NIL;
    3560 GIC          19 :                     List       *newdef = NIL;
    3561                 :                     AttrNumber  attnum;
    3562                 :                     Oid         seq_relid;
    3563                 : 
    3564                 :                     /*
    3565                 :                      * Split options into those handled by ALTER SEQUENCE and
    3566                 :                      * those for ALTER TABLE proper.
    3567 ECB             :                      */
    3568 CBC          50 :                     foreach(lc, castNode(List, cmd->def))
    3569 EUB             :                     {
    3570 GIC          31 :                         DefElem    *def = lfirst_node(DefElem, lc);
    3571                 : 
    3572              31 :                         if (strcmp(def->defname, "generated") == 0)
    3573              13 :                             newdef = lappend(newdef, def);
    3574 ECB             :                         else
    3575 CBC          18 :                             newseqopts = lappend(newseqopts, def);
    3576                 :                     }
    3577 ECB             : 
    3578 CBC          19 :                     attnum = get_attnum(relid, cmd->name);
    3579              19 :                     if (attnum == InvalidAttrNumber)
    3580 UIC           0 :                         ereport(ERROR,
    3581 ECB             :                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
    3582                 :                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
    3583                 :                                         cmd->name, RelationGetRelationName(rel))));
    3584                 : 
    3585 CBC          19 :                     seq_relid = getIdentitySequence(relid, attnum, true);
    3586 ECB             : 
    3587 GIC          19 :                     if (seq_relid)
    3588                 :                     {
    3589 ECB             :                         AlterSeqStmt *seqstmt;
    3590                 : 
    3591 GIC          13 :                         seqstmt = makeNode(AlterSeqStmt);
    3592              13 :                         seqstmt->sequence = makeRangeVar(get_namespace_name(get_rel_namespace(seq_relid)),
    3593 ECB             :                                                          get_rel_name(seq_relid), -1);
    3594 GIC          13 :                         seqstmt->options = newseqopts;
    3595 CBC          13 :                         seqstmt->for_identity = true;
    3596              13 :                         seqstmt->missing_ok = false;
    3597                 : 
    3598 GIC          13 :                         cxt.blist = lappend(cxt.blist, seqstmt);
    3599 ECB             :                     }
    3600                 : 
    3601                 :                     /*
    3602                 :                      * If column was not an identity column, we just let the
    3603                 :                      * ALTER TABLE command error out later.  (There are cases
    3604                 :                      * this fails to cover, but we'll need to restructure
    3605 EUB             :                      * where creation of the sequence dependency linkage
    3606                 :                      * happens before we can fix it.)
    3607                 :                      */
    3608                 : 
    3609 GIC          19 :                     cmd->def = (Node *) newdef;
    3610 CBC          19 :                     newcmds = lappend(newcmds, cmd);
    3611 GIC          19 :                     break;
    3612                 :                 }
    3613                 : 
    3614            1490 :             case AT_AttachPartition:
    3615 ECB             :             case AT_DetachPartition:
    3616                 :                 {
    3617 GIC        1490 :                     PartitionCmd *partcmd = (PartitionCmd *) cmd->def;
    3618                 : 
    3619 CBC        1490 :                     transformPartitionCmd(&cxt, partcmd);
    3620                 :                     /* assign transformed value of the partition bound */
    3621 GIC        1472 :                     partcmd->bound = cxt.partbound;
    3622                 :                 }
    3623                 : 
    3624            1472 :                 newcmds = lappend(newcmds, cmd);
    3625            1472 :                 break;
    3626 ECB             : 
    3627 LBC           0 :             default:
    3628                 : 
    3629                 :                 /*
    3630                 :                  * Currently, we shouldn't actually get here for subcommand
    3631                 :                  * types that don't require transformation; but if we do, just
    3632                 :                  * emit them unchanged.
    3633                 :                  */
    3634 UIC           0 :                 newcmds = lappend(newcmds, cmd);
    3635 LBC           0 :                 break;
    3636                 :         }
    3637 ECB             :     }
    3638                 : 
    3639                 :     /*
    3640                 :      * Transfer anything we already have in cxt.alist into save_alist, to keep
    3641                 :      * it separate from the output of transformIndexConstraints.
    3642                 :      */
    3643 GIC       38351 :     save_alist = cxt.alist;
    3644           38351 :     cxt.alist = NIL;
    3645 ECB             : 
    3646                 :     /* Postprocess constraints */
    3647 GBC       38351 :     transformIndexConstraints(&cxt);
    3648 GIC       38345 :     transformFKConstraints(&cxt, skipValidation, true);
    3649           38345 :     transformCheckConstraints(&cxt, false);
    3650                 : 
    3651                 :     /*
    3652 ECB             :      * Push any index-creation commands into the ALTER, so that they can be
    3653                 :      * scheduled nicely by tablecmds.c.  Note that tablecmds.c assumes that
    3654                 :      * the IndexStmt attached to an AT_AddIndex or AT_AddIndexConstraint
    3655                 :      * subcommand has already been through transformIndexStmt.
    3656                 :      */
    3657 GIC       91428 :     foreach(l, cxt.alist)
    3658 ECB             :     {
    3659 CBC       53083 :         Node       *istmt = (Node *) lfirst(l);
    3660                 : 
    3661 ECB             :         /*
    3662                 :          * We assume here that cxt.alist contains only IndexStmts and possibly
    3663                 :          * AT_SetAttNotNull statements generated from primary key constraints.
    3664                 :          * We absorb the subcommands of the latter directly.
    3665                 :          */
    3666 GIC       53083 :         if (IsA(istmt, IndexStmt))
    3667                 :         {
    3668           33907 :             IndexStmt  *idxstmt = (IndexStmt *) istmt;
    3669                 : 
    3670           33907 :             idxstmt = transformIndexStmt(relid, idxstmt, queryString);
    3671           33907 :             newcmd = makeNode(AlterTableCmd);
    3672           33907 :             newcmd->subtype = OidIsValid(idxstmt->indexOid) ? AT_AddIndexConstraint : AT_AddIndex;
    3673           33907 :             newcmd->def = (Node *) idxstmt;
    3674           33907 :             newcmds = lappend(newcmds, newcmd);
    3675                 :         }
    3676 CBC       19176 :         else if (IsA(istmt, AlterTableStmt))
    3677 ECB             :         {
    3678 CBC       19176 :             AlterTableStmt *alterstmt = (AlterTableStmt *) istmt;
    3679                 : 
    3680 GIC       19176 :             newcmds = list_concat(newcmds, alterstmt->cmds);
    3681 ECB             :         }
    3682                 :         else
    3683 UIC           0 :             elog(ERROR, "unexpected stmt type %d", (int) nodeTag(istmt));
    3684 ECB             :     }
    3685 GIC       38345 :     cxt.alist = NIL;
    3686 ECB             : 
    3687                 :     /* Append any CHECK or FK constraints to the commands list */
    3688 CBC       38717 :     foreach(l, cxt.ckconstraints)
    3689                 :     {
    3690 GIC         372 :         newcmd = makeNode(AlterTableCmd);
    3691 CBC         372 :         newcmd->subtype = AT_AddConstraint;
    3692 GNC         372 :         newcmd->def = (Node *) lfirst_node(Constraint, l);
    3693 GIC         372 :         newcmds = lappend(newcmds, newcmd);
    3694 EUB             :     }
    3695 GIC       39378 :     foreach(l, cxt.fkconstraints)
    3696                 :     {
    3697            1033 :         newcmd = makeNode(AlterTableCmd);
    3698            1033 :         newcmd->subtype = AT_AddConstraint;
    3699 GNC        1033 :         newcmd->def = (Node *) lfirst_node(Constraint, l);
    3700            1033 :         newcmds = lappend(newcmds, newcmd);
    3701                 :     }
    3702           38572 :     foreach(l, cxt.nnconstraints)
    3703                 :     {
    3704             227 :         newcmd = makeNode(AlterTableCmd);
    3705             227 :         newcmd->subtype = AT_AddConstraint;
    3706             227 :         newcmd->def = (Node *) lfirst_node(Constraint, l);
    3707 GIC         227 :         newcmds = lappend(newcmds, newcmd);
    3708 EUB             :     }
    3709                 : 
    3710                 :     /* Append extended statistics objects */
    3711 GIC       38345 :     transformExtendedStatistics(&cxt);
    3712                 : 
    3713                 :     /* Close rel */
    3714           38345 :     relation_close(rel, NoLock);
    3715                 : 
    3716                 :     /*
    3717 ECB             :      * Output results.
    3718                 :      */
    3719 GIC       38345 :     stmt->cmds = newcmds;
    3720                 : 
    3721 CBC       38345 :     *beforeStmts = cxt.blist;
    3722           38345 :     *afterStmts = list_concat(cxt.alist, save_alist);
    3723 ECB             : 
    3724 GIC       38345 :     return stmt;
    3725                 : }
    3726                 : 
    3727                 : 
    3728                 : /*
    3729                 :  * Preprocess a list of column constraint clauses
    3730                 :  * to attach constraint attributes to their primary constraint nodes
    3731 ECB             :  * and detect inconsistent/misplaced constraint attributes.
    3732                 :  *
    3733                 :  * NOTE: currently, attributes are only supported for FOREIGN KEY, UNIQUE,
    3734                 :  * EXCLUSION, and PRIMARY KEY constraints, but someday they ought to be
    3735                 :  * supported for other constraint types.
    3736                 :  */
    3737                 : static void
    3738 GIC       34730 : transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList)
    3739                 : {
    3740 CBC       34730 :     Constraint *lastprimarycon = NULL;
    3741 GIC       34730 :     bool        saw_deferrability = false;
    3742 CBC       34730 :     bool        saw_initially = false;
    3743                 :     ListCell   *clist;
    3744 ECB             : 
    3745                 : #define SUPPORTS_ATTRS(node)                \
    3746                 :     ((node) != NULL &&                      \
    3747                 :      ((node)->contype == CONSTR_PRIMARY ||   \
    3748                 :       (node)->contype == CONSTR_UNIQUE ||    \
    3749                 :       (node)->contype == CONSTR_EXCLUSION || \
    3750                 :       (node)->contype == CONSTR_FOREIGN))
    3751                 : 
    3752 CBC       42310 :     foreach(clist, constraintList)
    3753                 :     {
    3754            7580 :         Constraint *con = (Constraint *) lfirst(clist);
    3755                 : 
    3756 GIC        7580 :         if (!IsA(con, Constraint))
    3757 UBC           0 :             elog(ERROR, "unrecognized node type: %d",
    3758                 :                  (int) nodeTag(con));
    3759 CBC        7580 :         switch (con->contype)
    3760                 :         {
    3761 GIC          41 :             case CONSTR_ATTR_DEFERRABLE:
    3762 CBC          41 :                 if (!SUPPORTS_ATTRS(lastprimarycon))
    3763 UIC           0 :                     ereport(ERROR,
    3764 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3765                 :                              errmsg("misplaced DEFERRABLE clause"),
    3766                 :                              parser_errposition(cxt->pstate, con->location)));
    3767 CBC          41 :                 if (saw_deferrability)
    3768 UIC           0 :                     ereport(ERROR,
    3769 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3770                 :                              errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
    3771                 :                              parser_errposition(cxt->pstate, con->location)));
    3772 CBC          41 :                 saw_deferrability = true;
    3773              41 :                 lastprimarycon->deferrable = true;
    3774              41 :                 break;
    3775                 : 
    3776 LBC           0 :             case CONSTR_ATTR_NOT_DEFERRABLE:
    3777 UIC           0 :                 if (!SUPPORTS_ATTRS(lastprimarycon))
    3778 LBC           0 :                     ereport(ERROR,
    3779 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3780                 :                              errmsg("misplaced NOT DEFERRABLE clause"),
    3781                 :                              parser_errposition(cxt->pstate, con->location)));
    3782 UIC           0 :                 if (saw_deferrability)
    3783               0 :                     ereport(ERROR,
    3784                 :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3785 ECB             :                              errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
    3786                 :                              parser_errposition(cxt->pstate, con->location)));
    3787 UIC           0 :                 saw_deferrability = true;
    3788 LBC           0 :                 lastprimarycon->deferrable = false;
    3789 UIC           0 :                 if (saw_initially &&
    3790               0 :                     lastprimarycon->initdeferred)
    3791               0 :                     ereport(ERROR,
    3792                 :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3793 ECB             :                              errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
    3794                 :                              parser_errposition(cxt->pstate, con->location)));
    3795 LBC           0 :                 break;
    3796 ECB             : 
    3797 GIC          30 :             case CONSTR_ATTR_DEFERRED:
    3798 CBC          30 :                 if (!SUPPORTS_ATTRS(lastprimarycon))
    3799 UIC           0 :                     ereport(ERROR,
    3800                 :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3801                 :                              errmsg("misplaced INITIALLY DEFERRED clause"),
    3802                 :                              parser_errposition(cxt->pstate, con->location)));
    3803 GIC          30 :                 if (saw_initially)
    3804 UIC           0 :                     ereport(ERROR,
    3805                 :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3806                 :                              errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
    3807                 :                              parser_errposition(cxt->pstate, con->location)));
    3808 GIC          30 :                 saw_initially = true;
    3809              30 :                 lastprimarycon->initdeferred = true;
    3810                 : 
    3811                 :                 /*
    3812 ECB             :                  * If only INITIALLY DEFERRED appears, assume DEFERRABLE
    3813                 :                  */
    3814 CBC          30 :                 if (!saw_deferrability)
    3815               5 :                     lastprimarycon->deferrable = true;
    3816              25 :                 else if (!lastprimarycon->deferrable)
    3817 UIC           0 :                     ereport(ERROR,
    3818                 :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3819                 :                              errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
    3820                 :                              parser_errposition(cxt->pstate, con->location)));
    3821 GIC          30 :                 break;
    3822                 : 
    3823               3 :             case CONSTR_ATTR_IMMEDIATE:
    3824               3 :                 if (!SUPPORTS_ATTRS(lastprimarycon))
    3825 UIC           0 :                     ereport(ERROR,
    3826 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3827                 :                              errmsg("misplaced INITIALLY IMMEDIATE clause"),
    3828                 :                              parser_errposition(cxt->pstate, con->location)));
    3829 GIC           3 :                 if (saw_initially)
    3830 LBC           0 :                     ereport(ERROR,
    3831 EUB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
    3832                 :                              errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
    3833 ECB             :                              parser_errposition(cxt->pstate, con->location)));
    3834 GIC           3 :                 saw_initially = true;
    3835 CBC           3 :                 lastprimarycon->initdeferred = false;
    3836               3 :                 break;
    3837 EUB             : 
    3838 GIC        7506 :             default:
    3839                 :                 /* Otherwise it's not an attribute */
    3840            7506 :                 lastprimarycon = con;
    3841 ECB             :                 /* reset flags for new primary node */
    3842 GBC        7506 :                 saw_deferrability = false;
    3843 GIC        7506 :                 saw_initially = false;
    3844            7506 :                 break;
    3845                 :         }
    3846 ECB             :     }
    3847 CBC       34730 : }
    3848 ECB             : 
    3849                 : /*
    3850 EUB             :  * Special handling of type definition for a column
    3851                 :  */
    3852                 : static void
    3853 GIC       34615 : transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
    3854                 : {
    3855                 :     /*
    3856 EUB             :      * All we really need to do here is verify that the type is valid,
    3857                 :      * including any collation spec that might be present.
    3858                 :      */
    3859 GIC       34615 :     Type        ctype = typenameType(cxt->pstate, column->typeName, NULL);
    3860                 : 
    3861 GBC       34608 :     if (column->collClause)
    3862 EUB             :     {
    3863 GBC         236 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(ctype);
    3864 EUB             : 
    3865 GBC         236 :         LookupCollation(cxt->pstate,
    3866 GIC         236 :                         column->collClause->collname,
    3867             236 :                         column->collClause->location);
    3868                 :         /* Complain if COLLATE is applied to an uncollatable type */
    3869 GBC         224 :         if (!OidIsValid(typtup->typcollation))
    3870 GIC           9 :             ereport(ERROR,
    3871 ECB             :                     (errcode(ERRCODE_DATATYPE_MISMATCH),
    3872                 :                      errmsg("collations are not supported by type %s",
    3873 EUB             :                             format_type_be(typtup->oid)),
    3874                 :                      parser_errposition(cxt->pstate,
    3875                 :                                         column->collClause->location)));
    3876                 :     }
    3877 ECB             : 
    3878 GBC       34587 :     ReleaseSysCache(ctype);
    3879 GIC       34587 : }
    3880                 : 
    3881                 : 
    3882 ECB             : /*
    3883                 :  * transformCreateSchemaStmt -
    3884                 :  *    analyzes the CREATE SCHEMA statement
    3885                 :  *
    3886                 :  * Split the schema element list into individual commands and place
    3887                 :  * them in the result list in an order such that there are no forward
    3888                 :  * references (e.g. GRANT to a table created later in the list). Note
    3889                 :  * that the logic we use for determining forward references is
    3890                 :  * presently quite incomplete.
    3891 EUB             :  *
    3892                 :  * SQL also allows constraints to make forward references, so thumb through
    3893                 :  * the table columns and move forward references to a posterior alter-table
    3894                 :  * command.
    3895 ECB             :  *
    3896                 :  * The result is a list of parse nodes that still need to be analyzed ---
    3897                 :  * but we can't analyze the later commands until we've executed the earlier
    3898                 :  * ones, because of possible inter-object references.
    3899 EUB             :  *
    3900                 :  * Note: this breaks the rules a little bit by modifying schema-name fields
    3901                 :  * within passed-in structs.  However, the transformation would be the same
    3902                 :  * if done over, so it should be all right to scribble on the input to this
    3903 ECB             :  * extent.
    3904 EUB             :  */
    3905                 : List *
    3906 GIC         649 : transformCreateSchemaStmt(CreateSchemaStmt *stmt)
    3907                 : {
    3908 ECB             :     CreateSchemaStmtContext cxt;
    3909                 :     List       *result;
    3910                 :     ListCell   *elements;
    3911                 : 
    3912 CBC         649 :     cxt.stmtType = "CREATE SCHEMA";
    3913 GIC         649 :     cxt.schemaname = stmt->schemaname;
    3914 CBC         649 :     cxt.authrole = (RoleSpec *) stmt->authrole;
    3915 GIC         649 :     cxt.sequences = NIL;
    3916 CBC         649 :     cxt.tables = NIL;
    3917             649 :     cxt.views = NIL;
    3918             649 :     cxt.indexes = NIL;
    3919 GIC         649 :     cxt.triggers = NIL;
    3920             649 :     cxt.grants = NIL;
    3921 ECB             : 
    3922                 :     /*
    3923                 :      * Run through each schema element in the schema element list. Separate
    3924                 :      * statements by type, and do preliminary analysis.
    3925                 :      */
    3926 GIC         824 :     foreach(elements, stmt->schemaElts)
    3927 ECB             :     {
    3928 GIC         175 :         Node       *element = lfirst(elements);
    3929                 : 
    3930             175 :         switch (nodeTag(element))
    3931                 :         {
    3932 UIC           0 :             case T_CreateSeqStmt:
    3933 ECB             :                 {
    3934 UIC           0 :                     CreateSeqStmt *elp = (CreateSeqStmt *) element;
    3935 ECB             : 
    3936 UIC           0 :                     setSchemaName(cxt.schemaname, &elp->sequence->schemaname);
    3937 LBC           0 :                     cxt.sequences = lappend(cxt.sequences, element);
    3938                 :                 }
    3939               0 :                 break;
    3940 ECB             : 
    3941 CBC         161 :             case T_CreateStmt:
    3942                 :                 {
    3943             161 :                     CreateStmt *elp = (CreateStmt *) element;
    3944 ECB             : 
    3945 GIC         161 :                     setSchemaName(cxt.schemaname, &elp->relation->schemaname);
    3946                 : 
    3947                 :                     /*
    3948                 :                      * XXX todo: deal with constraints
    3949                 :                      */
    3950             161 :                     cxt.tables = lappend(cxt.tables, element);
    3951                 :                 }
    3952 CBC         161 :                 break;
    3953 ECB             : 
    3954 GIC           7 :             case T_ViewStmt:
    3955                 :                 {
    3956               7 :                     ViewStmt   *elp = (ViewStmt *) element;
    3957                 : 
    3958               7 :                     setSchemaName(cxt.schemaname, &elp->view->schemaname);
    3959                 : 
    3960                 :                     /*
    3961                 :                      * XXX todo: deal with references between views
    3962                 :                      */
    3963               7 :                     cxt.views = lappend(cxt.views, element);
    3964                 :                 }
    3965               7 :                 break;
    3966                 : 
    3967               7 :             case T_IndexStmt:
    3968                 :                 {
    3969               7 :                     IndexStmt  *elp = (IndexStmt *) element;
    3970                 : 
    3971               7 :                     setSchemaName(cxt.schemaname, &elp->relation->schemaname);
    3972               7 :                     cxt.indexes = lappend(cxt.indexes, element);
    3973                 :                 }
    3974               7 :                 break;
    3975                 : 
    3976 UIC           0 :             case T_CreateTrigStmt:
    3977                 :                 {
    3978               0 :                     CreateTrigStmt *elp = (CreateTrigStmt *) element;
    3979                 : 
    3980 LBC           0 :                     setSchemaName(cxt.schemaname, &elp->relation->schemaname);
    3981 UIC           0 :                     cxt.triggers = lappend(cxt.triggers, element);
    3982                 :                 }
    3983               0 :                 break;
    3984                 : 
    3985               0 :             case T_GrantStmt:
    3986 LBC           0 :                 cxt.grants = lappend(cxt.grants, element);
    3987               0 :                 break;
    3988 ECB             : 
    3989 LBC           0 :             default:
    3990               0 :                 elog(ERROR, "unrecognized node type: %d",
    3991 ECB             :                      (int) nodeTag(element));
    3992                 :         }
    3993                 :     }
    3994                 : 
    3995 GIC         649 :     result = NIL;
    3996             649 :     result = list_concat(result, cxt.sequences);
    3997             649 :     result = list_concat(result, cxt.tables);
    3998             649 :     result = list_concat(result, cxt.views);
    3999             649 :     result = list_concat(result, cxt.indexes);
    4000 CBC         649 :     result = list_concat(result, cxt.triggers);
    4001 GIC         649 :     result = list_concat(result, cxt.grants);
    4002 ECB             : 
    4003 GIC         649 :     return result;
    4004 ECB             : }
    4005                 : 
    4006 EUB             : /*
    4007                 :  * setSchemaName
    4008                 :  *      Set or check schema name in an element of a CREATE SCHEMA command
    4009                 :  */
    4010                 : static void
    4011 GBC         175 : setSchemaName(char *context_schema, char **stmt_schema_name)
    4012                 : {
    4013             175 :     if (*stmt_schema_name == NULL)
    4014 GIC         175 :         *stmt_schema_name = context_schema;
    4015 LBC           0 :     else if (strcmp(context_schema, *stmt_schema_name) != 0)
    4016 UIC           0 :         ereport(ERROR,
    4017 ECB             :                 (errcode(ERRCODE_INVALID_SCHEMA_DEFINITION),
    4018                 :                  errmsg("CREATE specifies a schema (%s) "
    4019                 :                         "different from the one being created (%s)",
    4020                 :                         *stmt_schema_name, context_schema)));
    4021 GIC         175 : }
    4022                 : 
    4023                 : /*
    4024 ECB             :  * transformPartitionCmd
    4025                 :  *      Analyze the ATTACH/DETACH PARTITION command
    4026                 :  *
    4027                 :  * In case of the ATTACH PARTITION command, cxt->partbound is set to the
    4028                 :  * transformed value of cmd->bound.
    4029                 :  */
    4030                 : static void
    4031 GIC        1490 : transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd)
    4032 ECB             : {
    4033 GIC        1490 :     Relation    parentRel = cxt->rel;
    4034                 : 
    4035            1490 :     switch (parentRel->rd_rel->relkind)
    4036                 :     {
    4037 CBC        1295 :         case RELKIND_PARTITIONED_TABLE:
    4038                 :             /* transform the partition bound, if any */
    4039            1295 :             Assert(RelationGetPartitionKey(parentRel) != NULL);
    4040 GIC        1295 :             if (cmd->bound != NULL)
    4041 CBC        1043 :                 cxt->partbound = transformPartitionBound(cxt->pstate, parentRel,
    4042                 :                                                          cmd->bound);
    4043            1286 :             break;
    4044 GIC         189 :         case RELKIND_PARTITIONED_INDEX:
    4045 ECB             : 
    4046                 :             /*
    4047                 :              * A partitioned index cannot have a partition bound set.  ALTER
    4048                 :              * INDEX prevents that with its grammar, but not ALTER TABLE.
    4049                 :              */
    4050 GBC         189 :             if (cmd->bound != NULL)
    4051 GIC           3 :                 ereport(ERROR,
    4052 EUB             :                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    4053                 :                          errmsg("\"%s\" is not a partitioned table",
    4054                 :                                 RelationGetRelationName(parentRel))));
    4055 GBC         186 :             break;
    4056 GIC           6 :         case RELKIND_RELATION:
    4057 EUB             :             /* the table must be partitioned */
    4058 GIC           6 :             ereport(ERROR,
    4059 EUB             :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    4060                 :                      errmsg("table \"%s\" is not partitioned",
    4061                 :                             RelationGetRelationName(parentRel))));
    4062                 :             break;
    4063 UBC           0 :         case RELKIND_INDEX:
    4064 EUB             :             /* the index must be partitioned */
    4065 UIC           0 :             ereport(ERROR,
    4066                 :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    4067                 :                      errmsg("index \"%s\" is not partitioned",
    4068                 :                             RelationGetRelationName(parentRel))));
    4069 ECB             :             break;
    4070 LBC           0 :         default:
    4071 ECB             :             /* parser shouldn't let this case through */
    4072 LBC           0 :             elog(ERROR, "\"%s\" is not a partitioned table or index",
    4073 ECB             :                  RelationGetRelationName(parentRel));
    4074                 :             break;
    4075                 :     }
    4076 GIC        1472 : }
    4077 ECB             : 
    4078                 : /*
    4079                 :  * transformPartitionBound
    4080                 :  *
    4081                 :  * Transform a partition bound specification
    4082                 :  */
    4083                 : PartitionBoundSpec *
    4084 GIC        4618 : transformPartitionBound(ParseState *pstate, Relation parent,
    4085 ECB             :                         PartitionBoundSpec *spec)
    4086                 : {
    4087                 :     PartitionBoundSpec *result_spec;
    4088 CBC        4618 :     PartitionKey key = RelationGetPartitionKey(parent);
    4089 GBC        4618 :     char        strategy = get_partition_strategy(key);
    4090            4618 :     int         partnatts = get_partition_natts(key);
    4091 GIC        4618 :     List       *partexprs = get_partition_exprs(key);
    4092                 : 
    4093                 :     /* Avoid scribbling on input */
    4094            4618 :     result_spec = copyObject(spec);
    4095 ECB             : 
    4096 GIC        4618 :     if (spec->is_default)
    4097                 :     {
    4098                 :         /*
    4099                 :          * Hash partitioning does not support a default partition; there's no
    4100                 :          * use case for it (since the set of partitions to create is perfectly
    4101                 :          * defined), and if users do get into it accidentally, it's hard to
    4102                 :          * back out from it afterwards.
    4103                 :          */
    4104             275 :         if (strategy == PARTITION_STRATEGY_HASH)
    4105 CBC           3 :             ereport(ERROR,
    4106                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    4107 ECB             :                      errmsg("a hash-partitioned table may not have a default partition")));
    4108                 : 
    4109                 :         /*
    4110                 :          * In case of the default partition, parser had no way to identify the
    4111                 :          * partition strategy. Assign the parent's strategy to the default
    4112                 :          * partition bound spec.
    4113                 :          */
    4114 CBC         272 :         result_spec->strategy = strategy;
    4115 ECB             : 
    4116 GIC         272 :         return result_spec;
    4117 ECB             :     }
    4118                 : 
    4119 GIC        4343 :     if (strategy == PARTITION_STRATEGY_HASH)
    4120                 :     {
    4121             290 :         if (spec->strategy != PARTITION_STRATEGY_HASH)
    4122               6 :             ereport(ERROR,
    4123                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    4124 ECB             :                      errmsg("invalid bound specification for a hash partition"),
    4125                 :                      parser_errposition(pstate, exprLocation((Node *) spec))));
    4126                 : 
    4127 GIC         284 :         if (spec->modulus <= 0)
    4128               6 :             ereport(ERROR,
    4129 ECB             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    4130                 :                      errmsg("modulus for hash partition must be an integer value greater than zero")));
    4131                 : 
    4132 CBC         278 :         Assert(spec->remainder >= 0);
    4133                 : 
    4134 GIC         278 :         if (spec->remainder >= spec->modulus)
    4135               6 :             ereport(ERROR,
    4136                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    4137 EUB             :                      errmsg("remainder for hash partition must be less than modulus")));
    4138                 :     }
    4139 GBC        4053 :     else if (strategy == PARTITION_STRATEGY_LIST)
    4140                 :     {
    4141                 :         ListCell   *cell;
    4142                 :         char       *colname;
    4143                 :         Oid         coltype;
    4144 EUB             :         int32       coltypmod;
    4145                 :         Oid         partcollation;
    4146                 : 
    4147 GIC        2171 :         if (spec->strategy != PARTITION_STRATEGY_LIST)
    4148               9 :             ereport(ERROR,
    4149                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    4150 ECB             :                      errmsg("invalid bound specification for a list partition"),
    4151                 :                      parser_errposition(pstate, exprLocation((Node *) spec))));
    4152                 : 
    4153                 :         /* Get the only column's name in case we need to output an error */
    4154 GIC        2162 :         if (key->partattrs[0] != 0)
    4155            2111 :             colname = get_attname(RelationGetRelid(parent),
    4156            2111 :                                   key->partattrs[0], false);
    4157                 :         else
    4158 CBC          51 :             colname = deparse_expression((Node *) linitial(partexprs),
    4159 GIC          51 :                                          deparse_context_for(RelationGetRelationName(parent),
    4160                 :                                                              RelationGetRelid(parent)),
    4161                 :                                          false, false);
    4162 ECB             :         /* Need its type data too */
    4163 CBC        2162 :         coltype = get_partition_col_typid(key, 0);
    4164            2162 :         coltypmod = get_partition_col_typmod(key, 0);
    4165            2162 :         partcollation = get_partition_col_collation(key, 0);
    4166                 : 
    4167 GIC        2162 :         result_spec->listdatums = NIL;
    4168 CBC        5175 :         foreach(cell, spec->listdatums)
    4169                 :         {
    4170            3043 :             Node       *expr = lfirst(cell);
    4171                 :             Const      *value;
    4172                 :             ListCell   *cell2;
    4173                 :             bool        duplicate;
    4174                 : 
    4175 GIC        3043 :             value = transformPartitionBoundValue(pstate, expr,
    4176                 :                                                  colname, coltype, coltypmod,
    4177                 :                                                  partcollation);
    4178 ECB             : 
    4179                 :             /* Don't add to the result if the value is a duplicate */
    4180 GIC        3013 :             duplicate = false;
    4181            4482 :             foreach(cell2, result_spec->listdatums)
    4182                 :             {
    4183            1469 :                 Const      *value2 = lfirst_node(Const, cell2);
    4184                 : 
    4185            1469 :                 if (equal(value, value2))
    4186                 :                 {
    4187 UIC           0 :                     duplicate = true;
    4188 LBC           0 :                     break;
    4189                 :                 }
    4190 ECB             :             }
    4191 GIC        3013 :             if (duplicate)
    4192 UIC           0 :                 continue;
    4193 ECB             : 
    4194 GIC        3013 :             result_spec->listdatums = lappend(result_spec->listdatums,
    4195 ECB             :                                               value);
    4196                 :         }
    4197                 :     }
    4198 GIC        1882 :     else if (strategy == PARTITION_STRATEGY_RANGE)
    4199                 :     {
    4200            1882 :         if (spec->strategy != PARTITION_STRATEGY_RANGE)
    4201 CBC           9 :             ereport(ERROR,
    4202 ECB             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    4203                 :                      errmsg("invalid bound specification for a range partition"),
    4204                 :                      parser_errposition(pstate, exprLocation((Node *) spec))));
    4205                 : 
    4206 CBC        1873 :         if (list_length(spec->lowerdatums) != partnatts)
    4207 GIC           3 :             ereport(ERROR,
    4208 ECB             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    4209                 :                      errmsg("FROM must specify exactly one value per partitioning column")));
    4210 GIC        1870 :         if (list_length(spec->upperdatums) != partnatts)
    4211               3 :             ereport(ERROR,
    4212                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    4213 ECB             :                      errmsg("TO must specify exactly one value per partitioning column")));
    4214                 : 
    4215                 :         /*
    4216                 :          * Convert raw parse nodes into PartitionRangeDatum nodes and perform
    4217                 :          * any necessary validation.
    4218                 :          */
    4219 GIC        1834 :         result_spec->lowerdatums =
    4220            1867 :             transformPartitionRangeBounds(pstate, spec->lowerdatums,
    4221 ECB             :                                           parent);
    4222 CBC        1831 :         result_spec->upperdatums =
    4223 GIC        1834 :             transformPartitionRangeBounds(pstate, spec->upperdatums,
    4224                 :                                           parent);
    4225                 :     }
    4226                 :     else
    4227 UIC           0 :         elog(ERROR, "unexpected partition strategy: %d", (int) strategy);
    4228 ECB             : 
    4229 CBC        4235 :     return result_spec;
    4230 ECB             : }
    4231                 : 
    4232                 : /*
    4233                 :  * transformPartitionRangeBounds
    4234                 :  *      This converts the expressions for range partition bounds from the raw
    4235                 :  *      grammar representation to PartitionRangeDatum structs
    4236                 :  */
    4237                 : static List *
    4238 CBC        3701 : transformPartitionRangeBounds(ParseState *pstate, List *blist,
    4239 ECB             :                               Relation parent)
    4240                 : {
    4241 CBC        3701 :     List       *result = NIL;
    4242            3701 :     PartitionKey key = RelationGetPartitionKey(parent);
    4243 GIC        3701 :     List       *partexprs = get_partition_exprs(key);
    4244 ECB             :     ListCell   *lc;
    4245                 :     int         i,
    4246                 :                 j;
    4247                 : 
    4248 GIC        3701 :     i = j = 0;
    4249 CBC        8333 :     foreach(lc, blist)
    4250                 :     {
    4251 GIC        4659 :         Node       *expr = lfirst(lc);
    4252            4659 :         PartitionRangeDatum *prd = NULL;
    4253                 : 
    4254 ECB             :         /*
    4255                 :          * Infinite range bounds -- "minvalue" and "maxvalue" -- get passed in
    4256                 :          * as ColumnRefs.
    4257                 :          */
    4258 GIC        4659 :         if (IsA(expr, ColumnRef))
    4259 ECB             :         {
    4260 GIC         369 :             ColumnRef  *cref = (ColumnRef *) expr;
    4261 GBC         369 :             char       *cname = NULL;
    4262 EUB             : 
    4263                 :             /*
    4264                 :              * There should be a single field named either "minvalue" or
    4265 ECB             :              * "maxvalue".
    4266 EUB             :              */
    4267 GIC         369 :             if (list_length(cref->fields) == 1 &&
    4268 CBC         366 :                 IsA(linitial(cref->fields), String))
    4269 GIC         366 :                 cname = strVal(linitial(cref->fields));
    4270                 : 
    4271             369 :             if (cname == NULL)
    4272 ECB             :             {
    4273                 :                 /*
    4274                 :                  * ColumnRef is not in the desired single-field-name form. For
    4275                 :                  * consistency between all partition strategies, let the
    4276                 :                  * expression transformation report any errors rather than
    4277                 :                  * doing it ourselves.
    4278                 :                  */
    4279                 :             }
    4280 CBC         366 :             else if (strcmp("minvalue", cname) == 0)
    4281 ECB             :             {
    4282 GIC         186 :                 prd = makeNode(PartitionRangeDatum);
    4283             186 :                 prd->kind = PARTITION_RANGE_DATUM_MINVALUE;
    4284 CBC         186 :                 prd->value = NULL;
    4285 ECB             :             }
    4286 GIC         180 :             else if (strcmp("maxvalue", cname) == 0)
    4287                 :             {
    4288             174 :                 prd = makeNode(PartitionRangeDatum);
    4289             174 :                 prd->kind = PARTITION_RANGE_DATUM_MAXVALUE;
    4290             174 :                 prd->value = NULL;
    4291                 :             }
    4292                 :         }
    4293 ECB             : 
    4294 CBC        4659 :         if (prd == NULL)
    4295                 :         {
    4296 ECB             :             char       *colname;
    4297                 :             Oid         coltype;
    4298                 :             int32       coltypmod;
    4299                 :             Oid         partcollation;
    4300                 :             Const      *value;
    4301 EUB             : 
    4302                 :             /* Get the column's name in case we need to output an error */
    4303 CBC        4299 :             if (key->partattrs[i] != 0)
    4304 GIC        3890 :                 colname = get_attname(RelationGetRelid(parent),
    4305            3890 :                                       key->partattrs[i], false);
    4306                 :             else
    4307                 :             {
    4308             409 :                 colname = deparse_expression((Node *) list_nth(partexprs, j),
    4309             409 :                                              deparse_context_for(RelationGetRelationName(parent),
    4310                 :                                                                  RelationGetRelid(parent)),
    4311                 :                                              false, false);
    4312 CBC         409 :                 ++j;
    4313                 :             }
    4314                 : 
    4315 ECB             :             /* Need its type data too */
    4316 CBC        4299 :             coltype = get_partition_col_typid(key, i);
    4317            4299 :             coltypmod = get_partition_col_typmod(key, i);
    4318 GIC        4299 :             partcollation = get_partition_col_collation(key, i);
    4319                 : 
    4320            4299 :             value = transformPartitionBoundValue(pstate, expr,
    4321                 :                                                  colname,
    4322 ECB             :                                                  coltype, coltypmod,
    4323                 :                                                  partcollation);
    4324 GIC        4275 :             if (value->constisnull)
    4325 CBC           3 :                 ereport(ERROR,
    4326 ECB             :                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
    4327                 :                          errmsg("cannot specify NULL in range bound")));
    4328 GIC        4272 :             prd = makeNode(PartitionRangeDatum);
    4329            4272 :             prd->kind = PARTITION_RANGE_DATUM_VALUE;
    4330            4272 :             prd->value = (Node *) value;
    4331            4272 :             ++i;
    4332 ECB             :         }
    4333                 : 
    4334 CBC        4632 :         prd->location = exprLocation(expr);
    4335 ECB             : 
    4336 GIC        4632 :         result = lappend(result, prd);
    4337                 :     }
    4338                 : 
    4339                 :     /*
    4340                 :      * Once we see MINVALUE or MAXVALUE for one column, the remaining columns
    4341 ECB             :      * must be the same.
    4342                 :      */
    4343 CBC        3674 :     validateInfiniteBounds(pstate, result);
    4344                 : 
    4345            3665 :     return result;
    4346                 : }
    4347                 : 
    4348                 : /*
    4349                 :  * validateInfiniteBounds
    4350                 :  *
    4351                 :  * Check that a MAXVALUE or MINVALUE specification in a partition bound is
    4352                 :  * followed only by more of the same.
    4353                 :  */
    4354 ECB             : static void
    4355 GIC        3674 : validateInfiniteBounds(ParseState *pstate, List *blist)
    4356 ECB             : {
    4357                 :     ListCell   *lc;
    4358 CBC        3674 :     PartitionRangeDatumKind kind = PARTITION_RANGE_DATUM_VALUE;
    4359                 : 
    4360            8294 :     foreach(lc, blist)
    4361                 :     {
    4362            4629 :         PartitionRangeDatum *prd = lfirst_node(PartitionRangeDatum, lc);
    4363 ECB             : 
    4364 CBC        4629 :         if (kind == prd->kind)
    4365 GIC        4365 :             continue;
    4366                 : 
    4367             264 :         switch (kind)
    4368 ECB             :         {
    4369 GIC         255 :             case PARTITION_RANGE_DATUM_VALUE:
    4370             255 :                 kind = prd->kind;
    4371             255 :                 break;
    4372                 : 
    4373               3 :             case PARTITION_RANGE_DATUM_MAXVALUE:
    4374               3 :                 ereport(ERROR,
    4375                 :                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    4376                 :                          errmsg("every bound following MAXVALUE must also be MAXVALUE"),
    4377 ECB             :                          parser_errposition(pstate, exprLocation((Node *) prd))));
    4378                 :                 break;
    4379                 : 
    4380 GIC           6 :             case PARTITION_RANGE_DATUM_MINVALUE:
    4381               6 :                 ereport(ERROR,
    4382 ECB             :                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    4383                 :                          errmsg("every bound following MINVALUE must also be MINVALUE"),
    4384                 :                          parser_errposition(pstate, exprLocation((Node *) prd))));
    4385                 :                 break;
    4386                 :         }
    4387                 :     }
    4388 GIC        3665 : }
    4389                 : 
    4390 ECB             : /*
    4391                 :  * Transform one entry in a partition bound spec, producing a constant.
    4392                 :  */
    4393                 : static Const *
    4394 CBC        7342 : transformPartitionBoundValue(ParseState *pstate, Node *val,
    4395                 :                              const char *colName, Oid colType, int32 colTypmod,
    4396                 :                              Oid partCollation)
    4397                 : {
    4398 ECB             :     Node       *value;
    4399                 : 
    4400                 :     /* Transform raw parsetree */
    4401 GIC        7342 :     value = transformExpr(pstate, val, EXPR_KIND_PARTITION_BOUND);
    4402 ECB             : 
    4403                 :     /*
    4404                 :      * transformExpr() should have already rejected column references,
    4405                 :      * subqueries, aggregates, window functions, and SRFs, based on the
    4406                 :      * EXPR_KIND_ of a partition bound expression.
    4407                 :      */
    4408 CBC        7291 :     Assert(!contain_var_clause(value));
    4409                 : 
    4410 ECB             :     /*
    4411                 :      * Coerce to the correct type.  This might cause an explicit coercion step
    4412                 :      * to be added on top of the expression, which must be evaluated before
    4413                 :      * returning the result to the caller.
    4414                 :      */
    4415 GIC        7291 :     value = coerce_to_target_type(pstate,
    4416                 :                                   value, exprType(value),
    4417 ECB             :                                   colType,
    4418                 :                                   colTypmod,
    4419                 :                                   COERCION_ASSIGNMENT,
    4420                 :                                   COERCE_IMPLICIT_CAST,
    4421                 :                                   -1);
    4422                 : 
    4423 GIC        7291 :     if (value == NULL)
    4424               3 :         ereport(ERROR,
    4425                 :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    4426                 :                  errmsg("specified value cannot be cast to type %s for column \"%s\"",
    4427                 :                         format_type_be(colType), colName),
    4428                 :                  parser_errposition(pstate, exprLocation(val))));
    4429 ECB             : 
    4430                 :     /*
    4431                 :      * Evaluate the expression, if needed, assigning the partition key's data
    4432                 :      * type and collation to the resulting Const node.
    4433                 :      */
    4434 CBC        7288 :     if (!IsA(value, Const))
    4435                 :     {
    4436             260 :         assign_expr_collations(pstate, value);
    4437 GIC         260 :         value = (Node *) expression_planner((Expr *) value);
    4438 CBC         260 :         value = (Node *) evaluate_expr((Expr *) value, colType, colTypmod,
    4439 ECB             :                                        partCollation);
    4440 GIC         260 :         if (!IsA(value, Const))
    4441 LBC           0 :             elog(ERROR, "could not evaluate partition bound expression");
    4442                 :     }
    4443 ECB             :     else
    4444                 :     {
    4445                 :         /*
    4446                 :          * If the expression is already a Const, as is often the case, we can
    4447                 :          * skip the rather expensive steps above.  But we still have to insert
    4448                 :          * the right collation, since coerce_to_target_type doesn't handle
    4449                 :          * that.
    4450                 :          */
    4451 GIC        7028 :         ((Const *) value)->constcollid = partCollation;
    4452                 :     }
    4453                 : 
    4454 ECB             :     /*
    4455                 :      * Attach original expression's parse location to the Const, so that
    4456                 :      * that's what will be reported for any later errors related to this
    4457                 :      * partition bound.
    4458                 :      */
    4459 GIC        7288 :     ((Const *) value)->location = exprLocation(val);
    4460                 : 
    4461            7288 :     return (Const *) value;
    4462 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a