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 17:13:01 Functions: 100.0 % 29 29 29 28 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 95.5 % 67 64 3 63 1
Legend: Lines: hit not hit (120,180] days: 100.0 % 3 3 3
(240..) days: 89.2 % 1519 1355 66 89 9 48 846 5 456 106 852
Function coverage date bins:
(240..) days: 51.8 % 56 29 29 27

 Age         Owner                  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 *
 5769 tgl                       166 GIC       17260 : transformCreateStmt(CreateStmt *stmt, const char *queryString)
 5769 tgl                       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 */
 2944 alvherre                  178 GIC       17260 :     pstate = make_parsestate(NULL);
 2944 alvherre                  179 CBC       17260 :     pstate->p_sourcetext = queryString;
 2944 alvherre                  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                 :      */
 2944 alvherre                  187 GIC       17260 :     setup_parser_errposition_callback(&pcbstate, pstate,
 2944 alvherre                  188 CBC       17260 :                                       stmt->relation->location);
 4101 rhaas                     189 ECB             :     namespaceid =
 4101 rhaas                     190 GIC       17260 :         RangeVarGetAndCheckCreationNamespace(stmt->relation, NoLock,
 4101 rhaas                     191 ECB             :                                              &existing_relid);
 2944 alvherre                  192 GIC       17254 :     cancel_parser_errposition_callback(&pcbstate);
 4367 rhaas                     193 ECB             : 
                                194                 :     /*
                                195                 :      * If the relation already exists and the user specified "IF NOT EXISTS",
                                196                 :      * bail out with a NOTICE.
                                197                 :      */
 4101 rhaas                     198 GIC       17254 :     if (stmt->if_not_exists && OidIsValid(existing_relid))
 4367 rhaas                     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                 : 
  244 tgl                       206 GIC           5 :         ObjectAddressSet(address, RelationRelationId, existing_relid);
  244 tgl                       207 CBC           5 :         checkMembershipInCurrentExtension(&address);
  244 tgl                       208 ECB             : 
                                209                 :         /* OK to skip */
 4101 rhaas                     210 GIC           4 :         ereport(NOTICE,
 4101 rhaas                     211 ECB             :                 (errcode(ERRCODE_DUPLICATE_TABLE),
                                212                 :                  errmsg("relation \"%s\" already exists, skipping",
                                213                 :                         stmt->relation->relname)));
 4101 rhaas                     214 GIC           4 :         return NIL;
 4367 rhaas                     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                 :      */
 4500 rhaas                     224 GIC       17249 :     if (stmt->relation->schemaname == NULL
 4500 rhaas                     225 CBC       15870 :         && stmt->relation->relpersistence != RELPERSISTENCE_TEMP)
 5704 tgl                       226           14817 :         stmt->relation->schemaname = get_namespace_name(namespaceid);
 5704 tgl                       227 ECB             : 
                                228                 :     /* Set up CreateStmtContext */
 4457 tgl                       229 GIC       17249 :     cxt.pstate = pstate;
 4481 rhaas                     230 CBC       17249 :     if (IsA(stmt, CreateForeignTableStmt))
 3680 tgl                       231 ECB             :     {
 4481 rhaas                     232 GIC         219 :         cxt.stmtType = "CREATE FOREIGN TABLE";
 3680 tgl                       233 CBC         219 :         cxt.isforeign = true;
 3680 tgl                       234 ECB             :     }
                                235                 :     else
                                236                 :     {
 4481 rhaas                     237 GIC       17030 :         cxt.stmtType = "CREATE TABLE";
 3680 tgl                       238 CBC       17030 :         cxt.isforeign = false;
 3680 tgl                       239 ECB             :     }
 5769 tgl                       240 GIC       17249 :     cxt.relation = stmt->relation;
 5769 tgl                       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;
    2 alvherre                  248 GNC       17249 :     cxt.nnconstraints = NIL;
  871 tgl                       249 CBC       17249 :     cxt.likeclauses = NIL;
 1861 alvherre                  250           17249 :     cxt.extstats = NIL;
 5769 tgl                       251           17249 :     cxt.blist = NIL;
                                252           17249 :     cxt.alist = NIL;
                                253           17249 :     cxt.pkey = NULL;
 2314 rhaas                     254           17249 :     cxt.ispartitioned = stmt->partspec != NULL;
 1948 peter_e                   255           17249 :     cxt.partbound = stmt->partbound;
                                256           17249 :     cxt.ofType = (stmt->ofTypename != NULL);
 2906 tgl                       257 ECB             : 
 4790 bruce                     258 CBC       17249 :     Assert(!stmt->ofTypename || !stmt->inhRelations); /* grammar enforces */
                                259                 : 
 4819 peter_e                   260           17249 :     if (stmt->ofTypename)
 4457 tgl                       261 GIC          55 :         transformOfType(&cxt, stmt->ofTypename);
 4819 peter_e                   262 ECB             : 
 2314 rhaas                     263 CBC       17243 :     if (stmt->partspec)
                                264                 :     {
                                265            2187 :         if (stmt->inhRelations && !stmt->partbound)
 2314 rhaas                     266 GIC           3 :             ereport(ERROR,
 2314 rhaas                     267 ECB             :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 2118 tgl                       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                 :      */
 5769 tgl                       275 GIC       52306 :     foreach(elements, stmt->tableElts)
                                276                 :     {
 5769 tgl                       277 CBC       35151 :         Node       *element = lfirst(elements);
                                278                 : 
                                279           35151 :         switch (nodeTag(element))
                                280                 :         {
                                281           33904 :             case T_ColumnDef:
 4457 tgl                       282 GIC       33904 :                 transformColumnDefinition(&cxt, (ColumnDef *) element);
 5769 tgl                       283 CBC       33834 :                 break;
 5769 tgl                       284 ECB             : 
 2299 tgl                       285 CBC         899 :             case T_Constraint:
 2299 tgl                       286 GIC         899 :                 transformTableConstraint(&cxt, (Constraint *) element);
 5769 tgl                       287 CBC         890 :                 break;
 5769 tgl                       288 ECB             : 
 2299 tgl                       289 CBC         348 :             case T_TableLikeClause:
 2299 tgl                       290 GIC         348 :                 transformTableLikeClause(&cxt, (TableLikeClause *) element);
 2743 bruce                     291 CBC         342 :                 break;
 2743 bruce                     292 ECB             : 
 5769 tgl                       293 LBC           0 :             default:
 5769 tgl                       294 UIC           0 :                 elog(ERROR, "unrecognized node type: %d",
 5769 tgl                       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                 :      */
 5769 tgl                       306 GIC       17155 :     save_alist = cxt.alist;
                                307           17155 :     cxt.alist = NIL;
 5769 tgl                       308 ECB             : 
 5769 tgl                       309 CBC       17155 :     Assert(stmt->constraints == NIL);
                                310                 : 
 5769 tgl                       311 ECB             :     /*
                                312                 :      * Postprocess constraints that give rise to index definitions.
                                313                 :      */
 4457 tgl                       314 GIC       17155 :     transformIndexConstraints(&cxt);
                                315                 : 
  871 tgl                       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                 :      */
  871 tgl                       328 GIC       17155 :     cxt.alist = list_concat(cxt.alist, cxt.likeclauses);
                                329                 : 
 5769 tgl                       330 ECB             :     /*
                                331                 :      * Postprocess foreign-key constraints.
                                332                 :      */
 4457 tgl                       333 GIC       17155 :     transformFKConstraints(&cxt, true, false);
                                334                 : 
 2671 rhaas                     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                 :      */
  703 alvherre                  341 GIC       17155 :     transformCheckConstraints(&cxt, !cxt.isforeign);
                                342                 : 
 1861 alvherre                  343 ECB             :     /*
                                344                 :      * Postprocess extended statistics.
                                345                 :      */
 1861 alvherre                  346 GIC       17155 :     transformExtendedStatistics(&cxt);
                                347                 : 
 5769 tgl                       348 ECB             :     /*
                                349                 :      * Output results.
                                350                 :      */
 5769 tgl                       351 GIC       17155 :     stmt->tableElts = cxt.columns;
                                352           17155 :     stmt->constraints = cxt.ckconstraints;
    2 alvherre                  353 GNC       17155 :     stmt->nnconstraints = cxt.nnconstraints;
 5769 tgl                       354 ECB             : 
 5769 tgl                       355 CBC       17155 :     result = lappend(cxt.blist, stmt);
                                356           17155 :     result = list_concat(result, cxt.alist);
 5769 tgl                       357 GIC       17155 :     result = list_concat(result, save_alist);
 5769 tgl                       358 ECB             : 
 5769 tgl                       359 CBC       17155 :     return result;
 5769 tgl                       360 ECB             : }
                                361                 : 
 2128                           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
 2194 peter_e                   372 GIC         505 : generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
                                373                 :                          Oid seqtypid, List *seqoptions,
                                374                 :                          bool for_identity, bool col_exists,
 2194 peter_e                   375 ECB             :                          char **snamespace_p, char **sname_p)
                                376                 : {
                                377                 :     ListCell   *option;
 2153 bruce                     378 GIC         505 :     DefElem    *nameEl = NULL;
                                379                 :     Oid         snamespaceid;
                                380                 :     char       *snamespace;
 2194 peter_e                   381 ECB             :     char       *sname;
                                382                 :     CreateSeqStmt *seqstmt;
                                383                 :     AlterSeqStmt *altseqstmt;
                                384                 :     List       *attnamelist;
  899 drowley                   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 */
    9 drowley                   388 CBC         505 :     seqoptions = list_copy(seqoptions);
                                389                 : 
                                390                 :     /*
 2194 peter_e                   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                 :      */
 2194 peter_e                   404 GIC         616 :     foreach(option, seqoptions)
                                405                 :     {
 2190 tgl                       406             111 :         DefElem    *defel = lfirst_node(DefElem, option);
 2194 peter_e                   407 ECB             : 
 2194 peter_e                   408 GIC         111 :         if (strcmp(defel->defname, "sequence_name") == 0)
 2194 peter_e                   409 ECB             :         {
 2194 peter_e                   410 GIC          14 :             if (nameEl)
  633 dean.a.rasheed            411 LBC           0 :                 errorConflictingDefElem(defel, cxt->pstate);
 2194 peter_e                   412 GIC          14 :             nameEl = defel;
  899 drowley                   413 CBC          14 :             nameEl_idx = foreach_current_index(option);
 2194 peter_e                   414 EUB             :         }
 2194 peter_e                   415 ECB             :     }
                                416                 : 
 2194 peter_e                   417 GIC         505 :     if (nameEl)
                                418                 :     {
 2153 bruce                     419              14 :         RangeVar   *rv = makeRangeVarFromNameList(castNode(List, nameEl->arg));
 2153 bruce                     420 ECB             : 
 2194 peter_e                   421 GIC          14 :         snamespace = rv->schemaname;
 2128 tgl                       422 CBC          14 :         if (!snamespace)
                                423                 :         {
 2128 tgl                       424 ECB             :             /* Given unqualified SEQUENCE NAME, select namespace */
 2128 tgl                       425 LBC           0 :             if (cxt->rel)
 2128 tgl                       426 UIC           0 :                 snamespaceid = RelationGetNamespace(cxt->rel);
                                427                 :             else
 2128 tgl                       428 UBC           0 :                 snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
                                429               0 :             snamespace = get_namespace_name(snamespaceid);
                                430                 :         }
 2194 peter_e                   431 GBC          14 :         sname = rv->relname;
 2128 tgl                       432 EUB             :         /* Remove the SEQUENCE NAME item from seqoptions */
  899 drowley                   433 GIC          14 :         seqoptions = list_delete_nth_cell(seqoptions, nameEl_idx);
 2194 peter_e                   434 ECB             :     }
                                435                 :     else
                                436                 :     {
 2194 peter_e                   437 GIC         491 :         if (cxt->rel)
                                438              71 :             snamespaceid = RelationGetNamespace(cxt->rel);
                                439                 :         else
 2194 peter_e                   440 ECB             :         {
 2194 peter_e                   441 CBC         420 :             snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
 2194 peter_e                   442 GIC         420 :             RangeVarAdjustRelationPersistence(cxt->relation, snamespaceid);
                                443                 :         }
 2194 peter_e                   444 CBC         491 :         snamespace = get_namespace_name(snamespaceid);
                                445             491 :         sname = ChooseRelationName(cxt->relation->relname,
 2194 peter_e                   446 GIC         491 :                                    column->colname,
 2194 peter_e                   447 ECB             :                                    "seq",
 1678 tgl                       448                 :                                    snamespaceid,
                                449                 :                                    false);
                                450                 :     }
                                451                 : 
 2194 peter_e                   452 GIC         505 :     ereport(DEBUG1,
                                453                 :             (errmsg_internal("%s will create implicit sequence \"%s\" for serial column \"%s.%s\"",
                                454                 :                              cxt->stmtType, sname,
  697 tgl                       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                 :      */
 2194 peter_e                   461 GIC         505 :     seqstmt = makeNode(CreateSeqStmt);
                                462             505 :     seqstmt->for_identity = for_identity;
                                463             505 :     seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
  367 peter                     464 CBC         505 :     seqstmt->sequence->relpersistence = cxt->relation->relpersistence;
 2194 peter_e                   465             505 :     seqstmt->options = seqoptions;
 2153 bruce                     466 ECB             : 
 2194 peter_e                   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                 :      */
 2194 peter_e                   473 GIC         505 :     if (seqtypid)
 2128 tgl                       474             502 :         seqstmt->options = lcons(makeDefElem("as",
 2118                           475             502 :                                              (Node *) makeTypeNameFromOid(seqtypid, -1),
 2128 tgl                       476 ECB             :                                              -1),
 2194 peter_e                   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                 :      */
 2194 peter_e                   486 GIC         505 :     if (cxt->rel)
                                487              85 :         seqstmt->ownerId = cxt->rel->rd_rel->relowner;
                                488                 :     else
 2194 peter_e                   489 CBC         420 :         seqstmt->ownerId = InvalidOid;
 2194 peter_e                   490 ECB             : 
 2194 peter_e                   491 GIC         505 :     cxt->blist = lappend(cxt->blist, seqstmt);
 2194 peter_e                   492 ECB             : 
                                493                 :     /*
 1809 tgl                       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                 :      */
 1892 peter_e                   499 GIC         505 :     column->identitySequence = seqstmt->sequence;
                                500                 : 
                                501                 :     /*
 2153 bruce                     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                 :      */
 2194 peter_e                   510 GIC         505 :     altseqstmt = makeNode(AlterSeqStmt);
                                511             505 :     altseqstmt->sequence = makeRangeVar(snamespace, sname, -1);
                                512             505 :     attnamelist = list_make3(makeString(snamespace),
 2194 peter_e                   513 ECB             :                              makeString(cxt->relation->relname),
                                514                 :                              makeString(column->colname));
 2194 peter_e                   515 CBC         505 :     altseqstmt->options = list_make1(makeDefElem("owned_by",
                                516                 :                                                  (Node *) attnamelist, -1));
 2194 peter_e                   517 GIC         505 :     altseqstmt->for_identity = for_identity;
 2194 peter_e                   518 ECB             : 
 1180 tgl                       519 GIC         505 :     if (col_exists)
 1180 tgl                       520 CBC          51 :         cxt->blist = lappend(cxt->blist, altseqstmt);
                                521                 :     else
                                522             454 :         cxt->alist = lappend(cxt->alist, altseqstmt);
 2194 peter_e                   523 ECB             : 
 2194 peter_e                   524 GIC         505 :     if (snamespace_p)
 2194 peter_e                   525 CBC         349 :         *snamespace_p = snamespace;
 2194 peter_e                   526 GIC         505 :     if (sname_p)
 2194 peter_e                   527 CBC         349 :         *sname_p = sname;
                                528             505 : }
 2194 peter_e                   529 ECB             : 
 5769 tgl                       530                 : /*
                                531                 :  * transformColumnDefinition -
                                532                 :  *      transform a single ColumnDef within CREATE TABLE
                                533                 :  *      Also used in ALTER TABLE ADD COLUMN
                                534                 :  */
                                535                 : static void
 4457 tgl                       536 GIC       34758 : transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
                                537                 : {
                                538                 :     bool        is_serial;
 5769 tgl                       539 ECB             :     bool        saw_nullable;
                                540                 :     bool        saw_default;
                                541                 :     bool        saw_identity;
                                542                 :     bool        saw_generated;
    2 alvherre                  543 GNC       34758 :     bool        need_notnull = false;
                                544                 :     ListCell   *clist;
                                545                 : 
 5769 tgl                       546 GIC       34758 :     cxt->columns = lappend(cxt->columns, column);
 5769 tgl                       547 ECB             : 
                                548                 :     /* Check for SERIAL pseudo-types */
 5769 tgl                       549 GIC       34758 :     is_serial = false;
 4819 peter_e                   550 CBC       34758 :     if (column->typeName
 4819 peter_e                   551 GIC       34615 :         && list_length(column->typeName->names) == 1
                                552           18152 :         && !column->typeName->pct_type)
 5769 tgl                       553 ECB             :     {
 5015 peter_e                   554 CBC       18152 :         char       *typname = strVal(linitial(column->typeName->names));
 5769 tgl                       555 ECB             : 
 4310 rhaas                     556 CBC       18152 :         if (strcmp(typname, "smallserial") == 0 ||
 4310 rhaas                     557 GIC       18148 :             strcmp(typname, "serial2") == 0)
 4310 rhaas                     558 ECB             :         {
 4310 rhaas                     559 GIC           7 :             is_serial = true;
 4310 rhaas                     560 CBC           7 :             column->typeName->names = NIL;
                                561               7 :             column->typeName->typeOid = INT2OID;
                                562                 :         }
                                563           18145 :         else if (strcmp(typname, "serial") == 0 ||
 3955 bruce                     564           17813 :                  strcmp(typname, "serial4") == 0)
 5769 tgl                       565 ECB             :         {
 5769 tgl                       566 GIC         332 :             is_serial = true;
 5015 peter_e                   567 CBC         332 :             column->typeName->names = NIL;
                                568             332 :             column->typeName->typeOid = INT4OID;
                                569                 :         }
 5769 tgl                       570           17813 :         else if (strcmp(typname, "bigserial") == 0 ||
                                571           17809 :                  strcmp(typname, "serial8") == 0)
 5769 tgl                       572 ECB             :         {
 5769 tgl                       573 GIC          10 :             is_serial = true;
 5015 peter_e                   574 CBC          10 :             column->typeName->names = NIL;
                                575              10 :             column->typeName->typeOid = INT8OID;
                                576                 :         }
 5497 tgl                       577 ECB             : 
                                578                 :         /*
 5050 bruce                     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                 :          */
 5015 peter_e                   583 GIC       18152 :         if (is_serial && column->typeName->arrayBounds != NIL)
 5497 tgl                       584 UIC           0 :             ereport(ERROR,
                                585                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                586                 :                      errmsg("array of serial is not implemented"),
 4457 tgl                       587 ECB             :                      parser_errposition(cxt->pstate,
 4457 tgl                       588 EUB             :                                         column->typeName->location)));
                                589                 :     }
                                590                 : 
                                591                 :     /* Do necessary work on the column type declaration */
 4819 peter_e                   592 GIC       34758 :     if (column->typeName)
 4457 tgl                       593           34615 :         transformColumnType(cxt, column);
                                594                 : 
                                595                 :     /* Special actions for SERIAL pseudo-types */
 5769 tgl                       596 CBC       34730 :     if (is_serial)
 5769 tgl                       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                 : 
 2194 peter_e                   606 GIC         349 :         generateSerialExtraStmts(cxt, column,
 1180 tgl                       607             349 :                                  column->typeName->typeOid, NIL,
                                608                 :                                  false, false,
                                609                 :                                  &snamespace, &sname);
 5769 tgl                       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                 :          */
 5769 tgl                       621 GIC         349 :         qstring = quote_qualified_identifier(snamespace, sname);
                                622             349 :         snamenode = makeNode(A_Const);
  577 peter                     623             349 :         snamenode->val.node.type = T_String;
  450                           624             349 :         snamenode->val.sval.sval = qstring;
 5337 tgl                       625 CBC         349 :         snamenode->location = -1;
 5458 alvherre                  626             349 :         castnode = makeNode(TypeCast);
 5015 peter_e                   627             349 :         castnode->typeName = SystemTypeName("regclass");
 5458 alvherre                  628             349 :         castnode->arg = (Node *) snamenode;
 5337 tgl                       629             349 :         castnode->location = -1;
 3569 rhaas                     630             349 :         funccallnode = makeFuncCall(SystemFuncName("nextval"),
                                631             349 :                                     list_make1(castnode),
  886 tgl                       632 ECB             :                                     COERCE_EXPLICIT_CALL,
 3569 rhaas                     633                 :                                     -1);
 5769 tgl                       634 CBC         349 :         constraint = makeNode(Constraint);
                                635             349 :         constraint->contype = CONSTR_DEFAULT;
 5001 tgl                       636 GIC         349 :         constraint->location = -1;
 5769                           637             349 :         constraint->raw_expr = (Node *) funccallnode;
 5769 tgl                       638 CBC         349 :         constraint->cooked_expr = NULL;
                                639             349 :         column->constraints = lappend(column->constraints, constraint);
 5769 tgl                       640 ECB             : 
                                641                 :         /* have a NOT NULL constraint added later */
    2 alvherre                  642 GNC         349 :         need_notnull = true;
                                643                 :     }
 5769 tgl                       644 ECB             : 
                                645                 :     /* Process column constraints, if any... */
 4457 tgl                       646 GIC       34730 :     transformConstraintAttrs(cxt, column->constraints);
                                647                 : 
 5769 tgl                       648 CBC       34730 :     saw_nullable = false;
 5769 tgl                       649 GIC       34730 :     saw_default = false;
 2194 peter_e                   650 CBC       34730 :     saw_identity = false;
 1471 peter                     651           34730 :     saw_generated = false;
 5769 tgl                       652 ECB             : 
 5769 tgl                       653 CBC       42268 :     foreach(clist, column->constraints)
                                654                 :     {
 2190                           655            7580 :         Constraint *constraint = lfirst_node(Constraint, clist);
                                656                 : 
 5769                           657            7580 :         switch (constraint->contype)
                                658                 :         {
                                659              11 :             case CONSTR_NULL:
    2 alvherre                  660 GNC          11 :                 if ((saw_nullable && column->is_not_null) || need_notnull)
 5769 tgl                       661 CBC           3 :                     ereport(ERROR,
 5769 tgl                       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)));
 2062 peter_e                   667 GIC           8 :                 column->is_not_null = false;
 5769 tgl                       668               8 :                 saw_nullable = true;
 5769 tgl                       669 CBC           8 :                 break;
 5769 tgl                       670 ECB             : 
 5769 tgl                       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                 :                  */
    2 alvherre                  679 GNC        2686 :                 if (saw_nullable)
                                680                 :                 {
    2 alvherre                  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                 :                  */
    2 alvherre                  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                 : 
 5769 tgl                       724 CBC        2686 :                 break;
                                725                 : 
 5769 tgl                       726 GBC        1074 :             case CONSTR_DEFAULT:
                                727            1074 :                 if (saw_default)
 5769 tgl                       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)));
 5769 tgl                       734 GBC        1074 :                 column->raw_default = constraint->raw_expr;
 5769 tgl                       735 GIC        1074 :                 Assert(constraint->cooked_expr == NULL);
                                736            1074 :                 saw_default = true;
                                737            1074 :                 break;
                                738                 : 
 2194 peter_e                   739             114 :             case CONSTR_IDENTITY:
                                740                 :                 {
                                741                 :                     Type        ctype;
                                742                 :                     Oid         typeOid;
                                743                 : 
 1948                           744             114 :                     if (cxt->ofType)
                                745               3 :                         ereport(ERROR,
 1894 rhaas                     746 ECB             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                747                 :                                  errmsg("identity columns are not supported on typed tables")));
 1948 peter_e                   748 GIC         111 :                     if (cxt->partbound)
                                749               6 :                         ereport(ERROR,
 1948 peter_e                   750 ECB             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 1947 magnus                    751                 :                                  errmsg("identity columns are not supported on partitions")));
                                752                 : 
 2153 bruce                     753 CBC         105 :                     ctype = typenameType(cxt->pstate, column->typeName, NULL);
 1601 andres                    754             105 :                     typeOid = ((Form_pg_type) GETSTRUCT(ctype))->oid;
 2153 bruce                     755             105 :                     ReleaseSysCache(ctype);
 2194 peter_e                   756 ECB             : 
 2153 bruce                     757 CBC         105 :                     if (saw_identity)
                                758               3 :                         ereport(ERROR,
 2153 bruce                     759 ECB             :                                 (errcode(ERRCODE_SYNTAX_ERROR),
                                760                 :                                  errmsg("multiple identity specifications for column \"%s\" of table \"%s\"",
 2118 tgl                       761                 :                                         column->colname, cxt->relation->relname),
                                762                 :                                  parser_errposition(cxt->pstate,
 2153 bruce                     763                 :                                                     constraint->location)));
                                764                 : 
 2153 bruce                     765 GIC         102 :                     generateSerialExtraStmts(cxt, column,
 1180 tgl                       766 ECB             :                                              typeOid, constraint->options,
                                767                 :                                              true, false,
                                768                 :                                              NULL, NULL);
 2194 peter_e                   769                 : 
 2153 bruce                     770 GIC         102 :                     column->identity = constraint->generated_when;
 2153 bruce                     771 CBC         102 :                     saw_identity = true;
  758 tgl                       772 ECB             : 
                                773                 :                     /*
                                774                 :                      * Identity columns are always NOT NULL, but we may have a
                                775                 :                      * constraint already.
                                776                 :                      */
    2 alvherre                  777 GNC         102 :                     if (!saw_nullable)
                                778              90 :                         need_notnull = true;
                                779              12 :                     else if (!column->is_not_null)
  758 tgl                       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),
  758 tgl                       784 ECB             :                                  parser_errposition(cxt->pstate,
                                785                 :                                                     constraint->location)));
 2153 bruce                     786 GIC          99 :                     break;
 2153 bruce                     787 ECB             :                 }
                                788                 : 
 1471 peter                     789 GIC         412 :             case CONSTR_GENERATED:
                                790             412 :                 if (cxt->ofType)
                                791               3 :                     ereport(ERROR,
 1471 peter                     792 ECB             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                793                 :                              errmsg("generated columns are not supported on typed tables")));
 1471 peter                     794 GIC         409 :                 if (saw_generated)
                                795               3 :                     ereport(ERROR,
 1471 peter                     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)));
 1471 peter                     801 CBC         406 :                 column->generated = ATTRIBUTE_GENERATED_STORED;
 1471 peter                     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                 : 
 4871 tgl                       807             160 :             case CONSTR_CHECK:
 3035 tgl                       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                 :                  */
 3035 tgl                       814 GIC         160 :                 break;
                                815                 : 
                                816            2545 :             case CONSTR_PRIMARY:
 3680                           817            2545 :                 if (cxt->isforeign)
 3680 tgl                       818 CBC           3 :                     ereport(ERROR,
 3680 tgl                       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                 : 
 5769                           825                 :             case CONSTR_UNIQUE:
 3680 tgl                       826 CBC        2688 :                 if (cxt->isforeign)
 3680 tgl                       827 LBC           0 :                     ereport(ERROR,
 3680 tgl                       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)));
 5769 tgl                       832 GIC        2688 :                 if (constraint->keys == NIL)
                                833            2688 :                     constraint->keys = list_make1(makeString(column->colname));
 5769 tgl                       834 CBC        2688 :                 cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
 5769 tgl                       835 GIC        2688 :                 break;
                                836                 : 
 4871 tgl                       837 LBC           0 :             case CONSTR_EXCLUSION:
 4871 tgl                       838 ECB             :                 /* grammar does not allow EXCLUDE as a column constraint */
 4871 tgl                       839 LBC           0 :                 elog(ERROR, "column exclusion constraints are not supported");
                                840                 :                 break;
                                841                 : 
 5001 tgl                       842 CBC         358 :             case CONSTR_FOREIGN:
 3680                           843             358 :                 if (cxt->isforeign)
 3680 tgl                       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)));
 3602 bruce                     849 ECB             : 
 5001 tgl                       850                 :                 /*
                                851                 :                  * Fill in the current attribute's name and throw it into the
                                852                 :                  * list of FK constraints to be processed later.
                                853                 :                  */
 5001 tgl                       854 GIC         355 :                 constraint->fk_attrs = list_make1(makeString(column->colname));
 5001 tgl                       855 CBC         355 :                 cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
                                856             355 :                 break;
                                857                 : 
 5769 tgl                       858 GIC          74 :             case CONSTR_ATTR_DEFERRABLE:
                                859                 :             case CONSTR_ATTR_NOT_DEFERRABLE:
                                860                 :             case CONSTR_ATTR_DEFERRED:
                                861                 :             case CONSTR_ATTR_IMMEDIATE:
 5769 tgl                       862 ECB             :                 /* transformConstraintAttrs took care of these */
 5769 tgl                       863 GIC          74 :                 break;
 5769 tgl                       864 ECB             : 
 5769 tgl                       865 LBC           0 :             default:
                                866               0 :                 elog(ERROR, "unrecognized constraint type: %d",
                                867                 :                      constraint->contype);
                                868                 :                 break;
                                869                 :         }
                                870                 : 
 2194 peter_e                   871 GIC        7550 :         if (saw_default && saw_identity)
                                872               6 :             ereport(ERROR,
                                873                 :                     (errcode(ERRCODE_SYNTAX_ERROR),
 2194 peter_e                   874 ECB             :                      errmsg("both default and identity specified for column \"%s\" of table \"%s\"",
 2194 peter_e                   875 EUB             :                             column->colname, cxt->relation->relname),
                                876                 :                      parser_errposition(cxt->pstate,
                                877                 :                                         constraint->location)));
                                878                 : 
 1471 peter                     879 GIC        7544 :         if (saw_default && saw_generated)
 1471 peter                     880 CBC           3 :             ereport(ERROR,
 1471 peter                     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,
 1471 peter                     885 EUB             :                                         constraint->location)));
                                886                 : 
 1471 peter                     887 GBC        7541 :         if (saw_identity && saw_generated)
 1471 peter                     888 GIC           3 :             ereport(ERROR,
                                889                 :                     (errcode(ERRCODE_SYNTAX_ERROR),
 1471 peter                     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                 :      */
    2 alvherre                  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                 :      */
 4265 rhaas                     923 GIC       34688 :     if (column->fdwoptions != NIL)
                                924                 :     {
 4265 rhaas                     925 ECB             :         AlterTableStmt *stmt;
 3955 bruce                     926                 :         AlterTableCmd *cmd;
 4265 rhaas                     927                 : 
 4265 rhaas                     928 GIC          76 :         cmd = makeNode(AlterTableCmd);
 4265 rhaas                     929 CBC          76 :         cmd->subtype = AT_AlterColumnGenericOptions;
 4265 rhaas                     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;
 4265 rhaas                     934 ECB             : 
 4265 rhaas                     935 GIC          76 :         stmt = makeNode(AlterTableStmt);
 4265 rhaas                     936 GBC          76 :         stmt->relation = cxt->relation;
                                937              76 :         stmt->cmds = NIL;
 1002 michael                   938 GIC          76 :         stmt->objtype = OBJECT_FOREIGN_TABLE;
 4265 rhaas                     939              76 :         stmt->cmds = lappend(stmt->cmds, cmd);
                                940                 : 
                                941              76 :         cxt->alist = lappend(cxt->alist, stmt);
 4265 rhaas                     942 ECB             :     }
 5769 tgl                       943 CBC       34688 : }
                                944                 : 
                                945                 : /*
                                946                 :  * transformTableConstraint
                                947                 :  *      transform a Constraint node within CREATE TABLE or ALTER TABLE
                                948                 :  */
                                949                 : static void
 4457                           950           36310 : transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
 5769 tgl                       951 ECB             : {
 5769 tgl                       952 GIC       36310 :     switch (constraint->contype)
                                953                 :     {
                                954           19546 :         case CONSTR_PRIMARY:
 3035                           955           19546 :             if (cxt->isforeign)
                                956               3 :                 ereport(ERROR,
                                957                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 3035 tgl                       958 ECB             :                          errmsg("primary key constraints are not supported on foreign tables"),
                                959                 :                          parser_errposition(cxt->pstate,
                                960                 :                                             constraint->location)));
 3035 tgl                       961 GIC       19543 :             cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
                                962           19543 :             break;
                                963                 : 
 5769                           964           14774 :         case CONSTR_UNIQUE:
 3035                           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)));
 3035 tgl                       971 CBC       14771 :             cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
 3035 tgl                       972 GIC       14771 :             break;
                                973                 : 
 4871                           974              76 :         case CONSTR_EXCLUSION:
 3035 tgl                       975 CBC          76 :             if (cxt->isforeign)
 3035 tgl                       976 UIC           0 :                 ereport(ERROR,
 3035 tgl                       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)));
 2314 rhaas                     981 CBC          76 :             if (cxt->ispartitioned)
                                982              12 :                 ereport(ERROR,
 2314 rhaas                     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)));
 5769 tgl                       987 CBC          64 :             cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
 5769 tgl                       988 GIC          64 :             break;
                                989                 : 
                                990             552 :         case CONSTR_CHECK:
                                991             552 :             cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
                                992             552 :             break;
                                993                 : 
    2 alvherre                  994 GNC         117 :         case CONSTR_NOTNULL:
                                995             117 :             cxt->nnconstraints = lappend(cxt->nnconstraints, constraint);
                                996             117 :             break;
                                997                 : 
 5001 tgl                       998 CBC        1245 :         case CONSTR_FOREIGN:
 3035 tgl                       999 GIC        1245 :             if (cxt->isforeign)
 3035 tgl                      1000 UIC           0 :                 ereport(ERROR,
                               1001                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1002                 :                          errmsg("foreign key constraints are not supported on foreign tables"),
 3035 tgl                      1003 ECB             :                          parser_errposition(cxt->pstate,
                               1004                 :                                             constraint->location)));
 5001 tgl                      1005 CBC        1245 :             cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
                               1006            1245 :             break;
 5001 tgl                      1007 ECB             : 
 5769 tgl                      1008 LBC           0 :         case CONSTR_NULL:
 5769 tgl                      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:
 5769 tgl                      1014 UIC           0 :             elog(ERROR, "invalid context for constraint type %d",
 5769 tgl                      1015 ECB             :                  constraint->contype);
                               1016                 :             break;
                               1017                 : 
 5769 tgl                      1018 UIC           0 :         default:
                               1019               0 :             elog(ERROR, "unrecognized constraint type: %d",
                               1020                 :                  constraint->contype);
                               1021                 :             break;
                               1022                 :     }
 5769 tgl                      1023 GIC       36292 : }
 5769 tgl                      1024 ECB             : 
                               1025                 : /*
 4110 peter_e                  1026                 :  * transformTableLikeClause
                               1027                 :  *
                               1028                 :  * Change the LIKE <srctable> portion of a CREATE TABLE statement into
  961 tgl                      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                 :  */
 5769                          1035                 : static void
 4110 peter_e                  1036 CBC         348 : transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause)
                               1037                 : {
 5769 tgl                      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                 : 
 3680 tgl                      1046 CBC         348 :     setup_parser_errposition_callback(&pcbstate, cxt->pstate,
                               1047             348 :                                       table_like_clause->relation->location);
                               1048                 : 
 3680 tgl                      1049 ECB             :     /* we could support LIKE in many cases, but worry about it another day */
 3680 tgl                      1050 CBC         348 :     if (cxt->isforeign)
 3680 tgl                      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 */
 4054 peter_e                  1056 CBC         348 :     relation = relation_openrv(table_like_clause->relation, AccessShareLock);
 5769 tgl                      1057 ECB             : 
 3935 tgl                      1058 GIC         345 :     if (relation->rd_rel->relkind != RELKIND_RELATION &&
                               1059             193 :         relation->rd_rel->relkind != RELKIND_VIEW &&
 3689 kgrittn                  1060             187 :         relation->rd_rel->relkind != RELKIND_MATVIEW &&
 3935 tgl                      1061             187 :         relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
 2314 rhaas                    1062 CBC         184 :         relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
                               1063             184 :         relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
 5769 tgl                      1064 GIC           3 :         ereport(ERROR,
 5769 tgl                      1065 ECB             :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
  640 peter                    1066                 :                  errmsg("relation \"%s\" is invalid in LIKE clause",
                               1067                 :                         RelationGetRelationName(relation)),
                               1068                 :                  errdetail_relkind_not_supported(relation->rd_rel->relkind)));
 5769 tgl                      1069                 : 
 4054 peter_e                  1070 CBC         342 :     cancel_parser_errposition_callback(&pcbstate);
 4054 peter_e                  1071 ECB             : 
                               1072                 :     /*
                               1073                 :      * Check for privileges
 5769 tgl                      1074                 :      */
 4054 peter_e                  1075 GBC         342 :     if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
                               1076                 :     {
  147 peter                    1077 GNC           3 :         aclresult = object_aclcheck(TypeRelationId, relation->rd_rel->reltype, GetUserId(),
                               1078                 :                                      ACL_USAGE);
 4054 peter_e                  1079 GIC           3 :         if (aclresult != ACLCHECK_OK)
 1954 peter_e                  1080 LBC           0 :             aclcheck_error(aclresult, OBJECT_TYPE,
 4054                          1081               0 :                            RelationGetRelationName(relation));
                               1082                 :     }
 4054 peter_e                  1083 EUB             :     else
                               1084                 :     {
 4054 peter_e                  1085 GIC         339 :         aclresult = pg_class_aclcheck(RelationGetRelid(relation), GetUserId(),
                               1086                 :                                       ACL_SELECT);
                               1087             339 :         if (aclresult != ACLCHECK_OK)
 1954 peter_e                  1088 UIC           0 :             aclcheck_error(aclresult, get_relkind_objtype(relation->rd_rel->relkind),
 4054 peter_e                  1089 UBC           0 :                            RelationGetRelationName(relation));
                               1090                 :     }
                               1091                 : 
 5769 tgl                      1092 GIC         342 :     tupleDesc = RelationGetDescr(relation);
 1095 peter                    1093 EUB             : 
 5769 tgl                      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.
 5769 tgl                      1098 ECB             :      */
 5769 tgl                      1099 GIC        1066 :     for (parent_attno = 1; parent_attno <= tupleDesc->natts;
                               1100             724 :          parent_attno++)
                               1101                 :     {
 2058 andres                   1102             724 :         Form_pg_attribute attribute = TupleDescAttr(tupleDesc,
                               1103                 :                                                     parent_attno - 1);
 5769 tgl                      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)
 5769 tgl                      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                 :          */
 5769 tgl                      1119 GIC         718 :         def = makeNode(ColumnDef);
                               1120             718 :         def->colname = pstrdup(attributeName);
 5015 peter_e                  1121 CBC         718 :         def->typeName = makeTypeNameFromOid(attribute->atttypid,
 4414 tgl                      1122 ECB             :                                             attribute->atttypmod);
 5769 tgl                      1123 GIC         718 :         def->inhcount = 0;
                               1124             718 :         def->is_local = true;
 5769 tgl                      1125 CBC         718 :         def->is_not_null = attribute->attnotnull;
    2 alvherre                 1126 GNC         718 :         if (attribute->attnotnull)
                               1127             139 :             process_notnull_constraints = true;
 4414 tgl                      1128 GBC         718 :         def->is_from_type = false;
 4414 tgl                      1129 GIC         718 :         def->storage = 0;
 5769                          1130             718 :         def->raw_default = NULL;
                               1131             718 :         def->cooked_default = NULL;
 4414                          1132             718 :         def->collClause = NULL;
 4414 tgl                      1133 CBC         718 :         def->collOid = attribute->attcollation;
 5769 tgl                      1134 GIC         718 :         def->constraints = NIL;
 3426 tgl                      1135 CBC         718 :         def->location = -1;
 5769 tgl                      1136 ECB             : 
                               1137                 :         /*
                               1138                 :          * Add to column list
                               1139                 :          */
 5769 tgl                      1140 CBC         718 :         cxt->columns = lappend(cxt->columns, def);
 5769 tgl                      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                 :          */
  961 tgl                      1146 GIC         718 :         if (attribute->atthasdef && attribute->attgenerated &&
  961 tgl                      1147 CBC          24 :             (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED))
 1292 tgl                      1148 GIC          15 :             def->generated = attribute->attgenerated;
                               1149                 : 
                               1150                 :         /*
                               1151                 :          * Copy identity if requested
 2194 peter_e                  1152 ECB             :          */
 2194 peter_e                  1153 GIC         718 :         if (attribute->attidentity &&
 2194 peter_e                  1154 CBC           6 :             (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY))
                               1155                 :         {
 2153 bruce                    1156 ECB             :             Oid         seq_relid;
 2194 peter_e                  1157 EUB             :             List       *seq_options;
                               1158                 : 
                               1159                 :             /*
                               1160                 :              * find sequence owned by old column; extract sequence parameters;
                               1161                 :              * build new create sequence command
 2194 peter_e                  1162 ECB             :              */
 1357 peter                    1163 GIC           3 :             seq_relid = getIdentitySequence(RelationGetRelid(relation), attribute->attnum, false);
 2194 peter_e                  1164 CBC           3 :             seq_options = sequence_options(seq_relid);
 2194 peter_e                  1165 GBC           3 :             generateSerialExtraStmts(cxt, def,
 1180 tgl                      1166 EUB             :                                      InvalidOid, seq_options,
                               1167                 :                                      true, false,
                               1168                 :                                      NULL, NULL);
 2194 peter_e                  1169 CBC           3 :             def->identity = attribute->attidentity;
                               1170                 :         }
                               1171                 : 
                               1172                 :         /* Likewise, copy storage if requested */
 4110 peter_e                  1173 GIC         718 :         if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
 4927 andrew                   1174              66 :             def->storage = attribute->attstorage;
                               1175                 :         else
 4926 tgl                      1176 CBC         652 :             def->storage = 0;
 4927 andrew                   1177 ECB             : 
                               1178                 :         /* Likewise, copy compression if requested */
  751 rhaas                    1179 CBC         718 :         if ((table_like_clause->options & CREATE_TABLE_LIKE_COMPRESSION) != 0
  751 rhaas                    1180 GIC          42 :             && CompressionMethodIsValid(attribute->attcompression))
  751 rhaas                    1181 CBC           3 :             def->compression =
  751 rhaas                    1182 GIC           3 :                 pstrdup(GetCompressionMethodName(attribute->attcompression));
                               1183                 :         else
                               1184             715 :             def->compression = NULL;
                               1185                 : 
                               1186                 :         /* Likewise, copy comment if requested */
 4110 peter_e                  1187 CBC         778 :         if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
 4895 tgl                      1188              60 :             (comment = GetComment(attribute->attrelid,
                               1189                 :                                   RelationRelationId,
 4895 tgl                      1190 GIC          60 :                                   attribute->attnum)) != NULL)
                               1191                 :         {
 4927 andrew                   1192              39 :             CommentStmt *stmt = makeNode(CommentStmt);
                               1193                 : 
                               1194              39 :             stmt->objtype = OBJECT_COLUMN;
 2339 peter_e                  1195              39 :             stmt->object = (Node *) list_make3(makeString(cxt->relation->schemaname),
 2118 tgl                      1196 ECB             :                                                makeString(cxt->relation->relname),
 2339 peter_e                  1197                 :                                                makeString(def->colname));
 4927 andrew                   1198 CBC          39 :             stmt->comment = comment;
                               1199                 : 
                               1200              39 :             cxt->alist = lappend(cxt->alist, stmt);
 4927 andrew                   1201 ECB             :         }
 5769 tgl                      1202                 :     }
                               1203                 : 
  961                          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
  871                          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
  859                          1214                 :      * expandTableLikeClause is certain to open the same table.
  961                          1215                 :      */
    2 alvherre                 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)
  859 tgl                      1222 ECB             :     {
  859 tgl                      1223 GIC         322 :         table_like_clause->relationOid = RelationGetRelid(relation);
  871                          1224             322 :         cxt->likeclauses = lappend(cxt->likeclauses, table_like_clause);
                               1225                 :     }
                               1226                 : 
                               1227                 :     /*
  961 tgl                      1228 ECB             :      * We may copy extended statistics if requested, since the representation
                               1229                 :      * of CreateStatsStmt doesn't depend on column numbers.
                               1230                 :      */
  961 tgl                      1231 GIC         342 :     if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS)
                               1232                 :     {
                               1233                 :         List       *parent_extstats;
                               1234                 :         ListCell   *l;
  961 tgl                      1235 ECB             : 
  961 tgl                      1236 CBC          21 :         parent_extstats = RelationGetStatExtList(relation);
                               1237                 : 
  961 tgl                      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),
  961 tgl                      1245 ECB             :                                                     parent_stat_oid);
                               1246                 : 
                               1247                 :             /* Copy comment on statistics object, if requested */
  961 tgl                      1248 GIC          18 :             if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
                               1249                 :             {
                               1250              18 :                 comment = GetComment(parent_stat_oid, StatisticExtRelationId, 0);
  961 tgl                      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                 :                  */
  961 tgl                      1256 CBC          18 :                 stats_stmt->stxcomment = comment;
                               1257                 :             }
  961 tgl                      1258 ECB             : 
  961 tgl                      1259 GIC          18 :             cxt->extstats = lappend(cxt->extstats, stats_stmt);
                               1260                 :         }
  961 tgl                      1261 ECB             : 
  961 tgl                      1262 CBC          21 :         list_free(parent_extstats);
  961 tgl                      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                 :      */
  961 tgl                      1270 CBC         342 :     table_close(relation, NoLock);
  961 tgl                      1271 GIC         342 : }
  961 tgl                      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 *
  961 tgl                      1282 CBC         313 : expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
                               1283                 : {
  961 tgl                      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
  859 tgl                      1299 ECB             :      * etc.  We must open the rel by OID not name, to be sure we get the same
                               1300                 :      * table.
                               1301                 :      */
  859 tgl                      1302 GIC         313 :     if (!OidIsValid(table_like_clause->relationOid))
  859 tgl                      1303 LBC           0 :         elog(ERROR, "expandTableLikeClause called on untransformed LIKE clause");
                               1304                 : 
  859 tgl                      1305 GIC         313 :     relation = relation_open(table_like_clause->relationOid, NoLock);
  961 tgl                      1306 ECB             : 
  961 tgl                      1307 CBC         313 :     tupleDesc = RelationGetDescr(relation);
  961 tgl                      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);
  961 tgl                      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                 :      */
  961 tgl                      1320 GIC         313 :     attmap = build_attrmap_by_name(RelationGetDescr(childrel),
                               1321                 :                                    tupleDesc,
                               1322                 :                                    false);
                               1323                 : 
  961 tgl                      1324 ECB             :     /*
                               1325                 :      * Process defaults, if required.
                               1326                 :      */
  961 tgl                      1327 CBC         313 :     if ((table_like_clause->options &
  961 tgl                      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;
  961 tgl                      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)
  961 tgl                      1341 GIC           3 :                 continue;
                               1342                 : 
  961 tgl                      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                 :              */
  961 tgl                      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;
  733 tgl                      1354 CBC          28 :                 AttrDefault *attrdef = constr->defval;
  961 tgl                      1355 ECB             :                 AlterTableCmd *atsubcmd;
                               1356                 :                 bool        found_whole_row;
                               1357                 : 
                               1358                 :                 /* Find default in constraint structure */
  961 tgl                      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                 :                     }
  961 tgl                      1366 ECB             :                 }
  733 tgl                      1367 GIC          28 :                 if (this_default == NULL)
  733 tgl                      1368 LBC           0 :                     elog(ERROR, "default expression not found for attribute %d of relation \"%s\"",
  733 tgl                      1369 ECB             :                          parent_attno, RelationGetRelationName(relation));
                               1370                 : 
  961 tgl                      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)
  961 tgl                      1386 LBC           0 :                     ereport(ERROR,
  961 tgl                      1387 EUB             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1388                 :                              errmsg("cannot convert whole-row table reference"),
  961 tgl                      1389 ECB             :                              errdetail("Generation expression for column \"%s\" contains a whole-row reference to table \"%s\".",
                               1390                 :                                        NameStr(attribute->attname),
                               1391                 :                                        RelationGetRelationName(relation))));
                               1392                 : 
  961 tgl                      1393 GIC          28 :                 atsubcmds = lappend(atsubcmds, atsubcmd);
                               1394                 :             }
                               1395                 :         }
                               1396                 :     }
  961 tgl                      1397 ECB             : 
                               1398                 :     /*
                               1399                 :      * Copy CHECK constraints if requested, being careful to adjust attribute
                               1400                 :      * numbers so they match the child.
                               1401                 :      */
 4110 peter_e                  1402 GIC         313 :     if ((table_like_clause->options & CREATE_TABLE_LIKE_CONSTRAINTS) &&
                               1403                 :         constr != NULL)
 5769 tgl                      1404 ECB             :     {
                               1405                 :         int         ccnum;
                               1406                 : 
 1125 tgl                      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;
 1125 tgl                      1411 CBC          48 :             bool        ccnoinherit = constr->check[ccnum].ccnoinherit;
 3935 tgl                      1412 ECB             :             Node       *ccbin_node;
                               1413                 :             bool        found_whole_row;
                               1414                 :             Constraint *n;
  961                          1415                 :             AlterTableCmd *atsubcmd;
 5769                          1416                 : 
 3935 tgl                      1417 GIC          48 :             ccbin_node = map_variable_attnos(stringToNode(ccbin),
 3935 tgl                      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                 :              */
 3935 tgl                      1428 GIC          48 :             if (found_whole_row)
 3935 tgl                      1429 UIC           0 :                 ereport(ERROR,
                               1430                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1431                 :                          errmsg("cannot convert whole-row table reference"),
 3935 tgl                      1432 ECB             :                          errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".",
                               1433                 :                                    ccname,
                               1434                 :                                    RelationGetRelationName(relation))));
 5769                          1435                 : 
  961 tgl                      1436 GIC          48 :             n = makeNode(Constraint);
 5769 tgl                      1437 CBC          48 :             n->contype = CONSTR_CHECK;
 5001                          1438              48 :             n->conname = pstrdup(ccname);
 1125 tgl                      1439 GIC          48 :             n->location = -1;
                               1440              48 :             n->is_no_inherit = ccnoinherit;
 5769                          1441              48 :             n->raw_expr = NULL;
                               1442              48 :             n->cooked_expr = nodeToString(ccbin_node);
  961 tgl                      1443 ECB             : 
                               1444                 :             /* We can skip validation, since the new table should be empty. */
  961 tgl                      1445 CBC          48 :             n->skip_validation = true;
  961 tgl                      1446 GIC          48 :             n->initially_valid = true;
  961 tgl                      1447 ECB             : 
  961 tgl                      1448 CBC          48 :             atsubcmd = makeNode(AlterTableCmd);
  961 tgl                      1449 GIC          48 :             atsubcmd->subtype = AT_AddConstraint;
                               1450              48 :             atsubcmd->def = (Node *) n;
  961 tgl                      1451 CBC          48 :             atsubcmds = lappend(atsubcmds, atsubcmd);
 4927 andrew                   1452 EUB             : 
                               1453                 :             /* Copy comment on constraint */
 4110 peter_e                  1454 GIC          75 :             if ((table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) &&
 4023 peter_e                  1455 CBC          27 :                 (comment = GetComment(get_relation_constraint_oid(RelationGetRelid(relation),
 2118 tgl                      1456              27 :                                                                   n->conname, false),
 4895 tgl                      1457 ECB             :                                       ConstraintRelationId,
                               1458                 :                                       0)) != NULL)
                               1459                 :             {
 4927 andrew                   1460 GIC          15 :                 CommentStmt *stmt = makeNode(CommentStmt);
                               1461                 : 
 3029 alvherre                 1462              15 :                 stmt->objtype = OBJECT_TABCONSTRAINT;
  961 tgl                      1463              15 :                 stmt->object = (Node *) list_make3(makeString(heapRel->schemaname),
                               1464                 :                                                    makeString(heapRel->relname),
                               1465                 :                                                    makeString(n->conname));
 4927 andrew                   1466              15 :                 stmt->comment = comment;
                               1467                 : 
  961 tgl                      1468              15 :                 result = lappend(result, stmt);
 4927 andrew                   1469 ECB             :             }
 5769 tgl                      1470 EUB             :         }
                               1471                 :     }
                               1472                 : 
                               1473                 :     /*
                               1474                 :      * Copy NOT NULL constraints, too (these do not require any option to have
                               1475                 :      * been given).
                               1476                 :      */
    2 alvherre                 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.
  961 tgl                      1491 ECB             :      */
  961 tgl                      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;
  961 tgl                      1500 CBC         107 :         result = lcons(atcmd, result);
                               1501                 :     }
                               1502                 : 
                               1503                 :     /*
                               1504                 :      * Process indexes if required.
 5608 tgl                      1505 ECB             :      */
 4110 peter_e                  1506 GIC         313 :     if ((table_like_clause->options & CREATE_TABLE_LIKE_INDEXES) &&
 4927 andrew                   1507 CBC          40 :         relation->rd_rel->relhasindex)
 5745 neilc                    1508 ECB             :     {
                               1509                 :         List       *parent_indexes;
                               1510                 :         ListCell   *l;
                               1511                 : 
 5745 neilc                    1512 GIC          31 :         parent_indexes = RelationGetIndexList(relation);
                               1513                 : 
                               1514              87 :         foreach(l, parent_indexes)
 5745 neilc                    1515 ECB             :         {
 5624 bruce                    1516 GIC          56 :             Oid         parent_index_oid = lfirst_oid(l);
                               1517                 :             Relation    parent_index;
                               1518                 :             IndexStmt  *index_stmt;
                               1519                 : 
 5745 neilc                    1520              56 :             parent_index = index_open(parent_index_oid, AccessShareLock);
                               1521                 : 
                               1522                 :             /* Build CREATE INDEX statement to recreate the parent_index */
  961 tgl                      1523              56 :             index_stmt = generateClonedIndexStmt(heapRel,
                               1524                 :                                                  parent_index,
                               1525                 :                                                  attmap,
 1447 tgl                      1526 ECB             :                                                  NULL);
 5745 neilc                    1527 EUB             : 
                               1528                 :             /* Copy comment on index, if requested */
 4110 peter_e                  1529 GIC          56 :             if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS)
                               1530                 :             {
 4927 andrew                   1531              33 :                 comment = GetComment(parent_index_oid, RelationRelationId, 0);
                               1532                 : 
                               1533                 :                 /*
 3919 tgl                      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                 :                  */
 3919 tgl                      1537 CBC          33 :                 index_stmt->idxcomment = comment;
 4927 andrew                   1538 ECB             :             }
                               1539                 : 
  961 tgl                      1540 CBC          56 :             result = lappend(result, index_stmt);
                               1541                 : 
 5608 tgl                      1542 GIC          56 :             index_close(parent_index, AccessShareLock);
 5745 neilc                    1543 ECB             :         }
                               1544                 :     }
                               1545                 : 
  961 tgl                      1546                 :     /* Done with child rel */
  961 tgl                      1547 CBC         313 :     table_close(childrel, NoLock);
 1861 alvherre                 1548 ECB             : 
 5769 tgl                      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                 :      */
 1539 andres                   1554 CBC         313 :     table_close(relation, NoLock);
                               1555                 : 
  961 tgl                      1556 GIC         313 :     return result;
                               1557                 : }
 5769 tgl                      1558 ECB             : 
                               1559                 : static void
 4457 tgl                      1560 CBC          55 : transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
 4819 peter_e                  1561 ECB             : {
                               1562                 :     HeapTuple   tuple;
                               1563                 :     TupleDesc   tupdesc;
                               1564                 :     int         i;
                               1565                 :     Oid         ofTypeId;
                               1566                 : 
  163 peter                    1567 GNC          55 :     Assert(ofTypename);
                               1568                 : 
 4414 tgl                      1569 GIC          55 :     tuple = typenameType(NULL, ofTypename, NULL);
 4372 rhaas                    1570              52 :     check_of_type(tuple);
 1601 andres                   1571              49 :     ofTypeId = ((Form_pg_type) GETSTRUCT(tuple))->oid;
 2118 tgl                      1572              49 :     ofTypename->typeOid = ofTypeId; /* cached for later */
                               1573                 : 
 4819 peter_e                  1574              49 :     tupdesc = lookup_rowtype_tupdesc(ofTypeId, -1);
 4819 peter_e                  1575 CBC         144 :     for (i = 0; i < tupdesc->natts; i++)
                               1576                 :     {
 2058 andres                   1577 GIC          95 :         Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
                               1578                 :         ColumnDef  *n;
 4819 peter_e                  1579 ECB             : 
 4578 peter_e                  1580 CBC          95 :         if (attr->attisdropped)
 4578 peter_e                  1581 LBC           0 :             continue;
 4578 peter_e                  1582 ECB             : 
 4414 tgl                      1583 GIC          95 :         n = makeNode(ColumnDef);
 4813                          1584              95 :         n->colname = pstrdup(NameStr(attr->attname));
 4414                          1585              95 :         n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod);
                               1586              95 :         n->inhcount = 0;
 4819 peter_e                  1587              95 :         n->is_local = true;
 4414 tgl                      1588              95 :         n->is_not_null = false;
 4819 peter_e                  1589              95 :         n->is_from_type = true;
 4414 tgl                      1590 CBC          95 :         n->storage = 0;
 4414 tgl                      1591 GIC          95 :         n->raw_default = NULL;
 4414 tgl                      1592 CBC          95 :         n->cooked_default = NULL;
 4414 tgl                      1593 GIC          95 :         n->collClause = NULL;
 4414 tgl                      1594 CBC          95 :         n->collOid = attr->attcollation;
                               1595              95 :         n->constraints = NIL;
 3426                          1596              95 :         n->location = -1;
 4819 peter_e                  1597              95 :         cxt->columns = lappend(cxt->columns, n);
 4819 peter_e                  1598 ECB             :     }
  480 tgl                      1599 GIC          49 :     ReleaseTupleDesc(tupdesc);
                               1600                 : 
 4819 peter_e                  1601              49 :     ReleaseSysCache(tuple);
                               1602              49 : }
                               1603                 : 
 5769 tgl                      1604 ECB             : /*
 5608                          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.
 1447                          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).
 5769                          1621                 :  */
                               1622                 : IndexStmt *
 1447 tgl                      1623 GIC         759 : generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
                               1624                 :                         const AttrMap *attmap,
                               1625                 :                         Oid *constraintOid)
                               1626                 : {
 5608 tgl                      1627 CBC         759 :     Oid         source_relid = RelationGetRelid(source_idx);
                               1628                 :     HeapTuple   ht_idxrel;
 5608 tgl                      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;
 5624 bruce                    1638                 :     ListCell   *indexpr_item;
                               1639                 :     Oid         indrelid;
                               1640                 :     int         keyno;
                               1641                 :     Oid         keycoltype;
                               1642                 :     Datum       datum;
                               1643                 :     bool        isnull;
                               1644                 : 
 1447 tgl                      1645 CBC         759 :     if (constraintOid)
 1447 tgl                      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                 :      */
 4802 rhaas                    1652 CBC         759 :     ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(source_relid));
 5608 tgl                      1653 GIC         759 :     if (!HeapTupleIsValid(ht_idxrel))
 5608 tgl                      1654 LBC           0 :         elog(ERROR, "cache lookup failed for relation %u", source_relid);
 5608 tgl                      1655 GIC         759 :     idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
                               1656                 : 
                               1657                 :     /* Fetch pg_index tuple for source index from relcache entry */
 5608 tgl                      1658 CBC         759 :     ht_idx = source_idx->rd_indextuple;
 5745 neilc                    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 */
 2639 tgl                      1663             759 :     ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
                               1664             759 :     if (!HeapTupleIsValid(ht_am))
 2639 tgl                      1665 LBC           0 :         elog(ERROR, "cache lookup failed for access method %u",
                               1666                 :              idxrelrec->relam);
 2639 tgl                      1667 CBC         759 :     amrec = (Form_pg_am) GETSTRUCT(ht_am);
 5608 tgl                      1668 ECB             : 
 4397                          1669                 :     /* Extract indcollation from the pg_index tuple */
   15 dgustafsson              1670 GNC         759 :     datum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx,
                               1671                 :                                    Anum_pg_index_indcollation);
 4397 tgl                      1672 CBC         759 :     indcollation = (oidvector *) DatumGetPointer(datum);
                               1673                 : 
 4871 tgl                      1674 ECB             :     /* Extract indclass from the pg_index tuple */
   15 dgustafsson              1675 GNC         759 :     datum = SysCacheGetAttrNotNull(INDEXRELID, ht_idx, Anum_pg_index_indclass);
 5608 tgl                      1676 GBC         759 :     indclass = (oidvector *) DatumGetPointer(datum);
                               1677                 : 
 5608 tgl                      1678 ECB             :     /* Begin building the IndexStmt */
 5745 neilc                    1679 CBC         759 :     index = makeNode(IndexStmt);
 1906 alvherre                 1680             759 :     index->relation = heapRel;
 5608 tgl                      1681             759 :     index->accessMethod = pstrdup(NameStr(amrec->amname));
 5540                          1682             759 :     if (OidIsValid(idxrelrec->reltablespace))
                               1683               3 :         index->tableSpace = get_tablespace_name(idxrelrec->reltablespace);
 5540 tgl                      1684 ECB             :     else
 5540 tgl                      1685 CBC         756 :         index->tableSpace = NULL;
 3919                          1686             759 :     index->excludeOpNames = NIL;
                               1687             759 :     index->idxcomment = NULL;
 4457                          1688             759 :     index->indexOid = InvalidOid;
  277 rhaas                    1689 GNC         759 :     index->oldNumber = InvalidRelFileNumber;
 1100 noah                     1690 CBC         759 :     index->oldCreateSubid = InvalidSubTransactionId;
  277 rhaas                    1691 GNC         759 :     index->oldFirstRelfilelocatorSubid = InvalidSubTransactionId;
 5745 neilc                    1692 CBC         759 :     index->unique = idxrec->indisunique;
  430 peter                    1693 GIC         759 :     index->nulls_not_distinct = idxrec->indnullsnotdistinct;
 5745 neilc                    1694 CBC         759 :     index->primary = idxrec->indisprimary;
 2968 tgl                      1695 GIC         759 :     index->transformed = true;   /* don't need transformIndexStmt */
 5608 tgl                      1696 CBC         759 :     index->concurrent = false;
 2968                          1697             759 :     index->if_not_exists = false;
 1445 alvherre                 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                 :      */
 5745 neilc                    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                 :      */
 4457 tgl                      1714             759 :     if (index->primary || index->unique || idxrec->indisexclusion)
 5002                          1715             580 :     {
 4790 bruce                    1716             580 :         Oid         constraintId = get_index_constraint(source_relid);
                               1717                 : 
 5002 tgl                      1718 CBC         580 :         if (OidIsValid(constraintId))
                               1719                 :         {
                               1720                 :             HeapTuple   ht_constr;
                               1721                 :             Form_pg_constraint conrec;
 5002 tgl                      1722 ECB             : 
 1875 alvherre                 1723 GIC         562 :             if (constraintOid)
                               1724             536 :                 *constraintOid = constraintId;
                               1725                 : 
 4802 rhaas                    1726             562 :             ht_constr = SearchSysCache1(CONSTROID,
                               1727                 :                                         ObjectIdGetDatum(constraintId));
 5002 tgl                      1728             562 :             if (!HeapTupleIsValid(ht_constr))
 5002 tgl                      1729 UIC           0 :                 elog(ERROR, "cache lookup failed for constraint %u",
                               1730                 :                      constraintId);
 5002 tgl                      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 */
 4457                          1738             562 :             if (idxrec->indisexclusion)
                               1739                 :             {
 4790 bruce                    1740 ECB             :                 Datum      *elems;
                               1741                 :                 int         nElems;
                               1742                 :                 int         i;
                               1743                 : 
 4871 tgl                      1744 GIC           1 :                 Assert(conrec->contype == CONSTRAINT_EXCLUSION);
                               1745                 :                 /* Extract operator OIDs from the pg_constraint tuple */
   15 dgustafsson              1746 GNC           1 :                 datum = SysCacheGetAttrNotNull(CONSTROID, ht_constr,
                               1747                 :                                                Anum_pg_constraint_conexclop);
  282 peter                    1748               1 :                 deconstruct_array_builtin(DatumGetArrayTypeP(datum), OIDOID, &elems, NULL, &nElems);
                               1749                 : 
 4871 tgl                      1750 GIC           2 :                 for (i = 0; i < nElems; i++)
 4871 tgl                      1751 ECB             :                 {
 4871 tgl                      1752 CBC           1 :                     Oid         operid = DatumGetObjectId(elems[i]);
 4871 tgl                      1753 EUB             :                     HeapTuple   opertup;
                               1754                 :                     Form_pg_operator operform;
 4871 tgl                      1755 ECB             :                     char       *oprname;
                               1756                 :                     char       *nspname;
                               1757                 :                     List       *namelist;
                               1758                 : 
 4802 rhaas                    1759 GIC           1 :                     opertup = SearchSysCache1(OPEROID,
 4802 rhaas                    1760 ECB             :                                               ObjectIdGetDatum(operid));
 4871 tgl                      1761 GIC           1 :                     if (!HeapTupleIsValid(opertup))
 4871 tgl                      1762 UIC           0 :                         elog(ERROR, "cache lookup failed for operator %u",
 4871 tgl                      1763 ECB             :                              operid);
 4871 tgl                      1764 CBC           1 :                     operform = (Form_pg_operator) GETSTRUCT(opertup);
 4871 tgl                      1765 GIC           1 :                     oprname = pstrdup(NameStr(operform->oprname));
                               1766                 :                     /* For simplicity we always schema-qualify the op name */
 4871 tgl                      1767 CBC           1 :                     nspname = get_namespace_name(operform->oprnamespace);
                               1768               1 :                     namelist = list_make2(makeString(nspname),
 4871 tgl                      1769 ECB             :                                           makeString(oprname));
 4871 tgl                      1770 CBC           1 :                     index->excludeOpNames = lappend(index->excludeOpNames,
 4871 tgl                      1771 ECB             :                                                     namelist);
 4871 tgl                      1772 GIC           1 :                     ReleaseSysCache(opertup);
 4871 tgl                      1773 ECB             :                 }
                               1774                 :             }
                               1775                 : 
 5002 tgl                      1776 CBC         562 :             ReleaseSysCache(ht_constr);
 5002 tgl                      1777 ECB             :         }
                               1778                 :         else
 5002 tgl                      1779 CBC          18 :             index->isconstraint = false;
 5002 tgl                      1780 ECB             :     }
 5608                          1781                 :     else
 5002 tgl                      1782 CBC         179 :         index->isconstraint = false;
 5745 neilc                    1783 ECB             : 
                               1784                 :     /* Get the index expressions, if any */
 5608 tgl                      1785 CBC         759 :     datum = SysCacheGetAttr(INDEXRELID, ht_idx,
 5608 tgl                      1786 ECB             :                             Anum_pg_index_indexprs, &isnull);
 5608 tgl                      1787 GIC         759 :     if (!isnull)
                               1788                 :     {
                               1789                 :         char       *exprsString;
                               1790                 : 
 5493                          1791              39 :         exprsString = TextDatumGetCString(datum);
 5745 neilc                    1792              39 :         indexprs = (List *) stringToNode(exprsString);
                               1793                 :     }
 5608 tgl                      1794 ECB             :     else
 5608 tgl                      1795 GIC         720 :         indexprs = NIL;
                               1796                 : 
                               1797                 :     /* Build the list of IndexElem */
                               1798             759 :     index->indexParams = NIL;
 1828 teodor                   1799             759 :     index->indexIncludingParams = NIL;
                               1800                 : 
 5608 tgl                      1801             759 :     indexpr_item = list_head(indexprs);
 1828 teodor                   1802 CBC        1620 :     for (keyno = 0; keyno < idxrec->indnkeyatts; keyno++)
 5745 neilc                    1803 ECB             :     {
 5624 bruce                    1804                 :         IndexElem  *iparam;
 5745 neilc                    1805 GIC         861 :         AttrNumber  attnum = idxrec->indkey.values[keyno];
 2058 andres                   1806 CBC         861 :         Form_pg_attribute attr = TupleDescAttr(RelationGetDescr(source_idx),
                               1807                 :                                                keyno);
 5608 tgl                      1808 GIC         861 :         int16       opt = source_idx->rd_indoption[keyno];
                               1809                 : 
 5745 neilc                    1810             861 :         iparam = makeNode(IndexElem);
 5745 neilc                    1811 ECB             : 
 5745 neilc                    1812 CBC         861 :         if (AttributeNumberIsValid(attnum))
                               1813                 :         {
 5745 neilc                    1814 ECB             :             /* Simple index column */
                               1815                 :             char       *attname;
 5769 tgl                      1816                 : 
 1882 alvherre                 1817 GBC         822 :             attname = get_attname(indrelid, attnum, false);
 5745 neilc                    1818 GIC         822 :             keycoltype = get_atttype(indrelid, attnum);
 5769 tgl                      1819 ECB             : 
 5745 neilc                    1820 GIC         822 :             iparam->name = attname;
 5745 neilc                    1821 CBC         822 :             iparam->expr = NULL;
 5745 neilc                    1822 ECB             :         }
 5769 tgl                      1823                 :         else
                               1824                 :         {
                               1825                 :             /* Expressional index */
 5745 neilc                    1826                 :             Node       *indexkey;
                               1827                 :             bool        found_whole_row;
                               1828                 : 
 5745 neilc                    1829 GIC          39 :             if (indexpr_item == NULL)
 5745 neilc                    1830 UIC           0 :                 elog(ERROR, "too few entries in indexprs list");
 5745 neilc                    1831 GIC          39 :             indexkey = (Node *) lfirst(indexpr_item);
 1364 tgl                      1832 CBC          39 :             indexpr_item = lnext(indexprs, indexpr_item);
                               1833                 : 
 3935 tgl                      1834 ECB             :             /* Adjust Vars to match new table's column numbering */
 3935 tgl                      1835 GIC          39 :             indexkey = map_variable_attnos(indexkey,
 3935 tgl                      1836 ECB             :                                            1, 0,
                               1837                 :                                            attmap,
 2075 rhaas                    1838                 :                                            InvalidOid, &found_whole_row);
                               1839                 : 
  961 tgl                      1840                 :             /* As in expandTableLikeClause, reject whole-row variables */
 3935 tgl                      1841 GIC          39 :             if (found_whole_row)
 3935 tgl                      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))));
 5608 tgl                      1847 ECB             : 
 5745 neilc                    1848 GIC          39 :             iparam->name = NULL;
 5745 neilc                    1849 CBC          39 :             iparam->expr = indexkey;
 5745 neilc                    1850 EUB             : 
 5745 neilc                    1851 GIC          39 :             keycoltype = exprType(indexkey);
 5745 neilc                    1852 ECB             :         }
 5769 tgl                      1853                 : 
                               1854                 :         /* Copy the original index column name */
 2058 andres                   1855 CBC         861 :         iparam->indexcolname = pstrdup(NameStr(attr->attname));
 4855 tgl                      1856 ECB             : 
                               1857                 :         /* Add the collation name, if non-default */
 4397 tgl                      1858 CBC         861 :         iparam->collation = get_collation(indcollation->values[keyno], keycoltype);
                               1859                 : 
 5745 neilc                    1860 ECB             :         /* Add the operator class name, if non-default */
 5745 neilc                    1861 GIC         861 :         iparam->opclass = get_opclass(indclass->values[keyno], keycoltype);
 1105 akorotkov                1862             861 :         iparam->opclassopts =
                               1863             861 :             untransformRelOptions(get_attoptions(source_relid, keyno + 1));
 5769 tgl                      1864 ECB             : 
 5745 neilc                    1865 GIC         861 :         iparam->ordering = SORTBY_DEFAULT;
                               1866             861 :         iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
 5745 neilc                    1867 ECB             : 
                               1868                 :         /* Adjust options if necessary */
 1539 andres                   1869 GIC         861 :         if (source_idx->rd_indam->amcanorder)
 5769 tgl                      1870 ECB             :         {
                               1871                 :             /*
                               1872                 :              * If it supports sort ordering, copy DESC and NULLS opts. Don't
 5050 bruce                    1873                 :              * set non-default settings unnecessarily, though, so as to
                               1874                 :              * improve the chance of recognizing equivalence to constraint
                               1875                 :              * indexes.
                               1876                 :              */
 5745 neilc                    1877 GIC         861 :             if (opt & INDOPTION_DESC)
                               1878                 :             {
 5745 neilc                    1879 LBC           0 :                 iparam->ordering = SORTBY_DESC;
 5608 tgl                      1880               0 :                 if ((opt & INDOPTION_NULLS_FIRST) == 0)
 5608 tgl                      1881 UIC           0 :                     iparam->nulls_ordering = SORTBY_NULLS_LAST;
                               1882                 :             }
 5608 tgl                      1883 ECB             :             else
                               1884                 :             {
 5608 tgl                      1885 GIC         861 :                 if (opt & INDOPTION_NULLS_FIRST)
 5608 tgl                      1886 LBC           0 :                     iparam->nulls_ordering = SORTBY_NULLS_FIRST;
 5608 tgl                      1887 ECB             :             }
                               1888                 :         }
 5769                          1889                 : 
 5745 neilc                    1890 CBC         861 :         index->indexParams = lappend(index->indexParams, iparam);
                               1891                 :     }
                               1892                 : 
 1828 teodor                   1893 ECB             :     /* Handle included columns separately */
 1828 teodor                   1894 CBC         768 :     for (keyno = idxrec->indnkeyatts; keyno < idxrec->indnatts; keyno++)
                               1895                 :     {
 1828 teodor                   1896 ECB             :         IndexElem  *iparam;
 1828 teodor                   1897 GIC           9 :         AttrNumber  attnum = idxrec->indkey.values[keyno];
 1828 teodor                   1898 CBC           9 :         Form_pg_attribute attr = TupleDescAttr(RelationGetDescr(source_idx),
                               1899                 :                                                keyno);
 1828 teodor                   1900 ECB             : 
 1828 teodor                   1901 GIC           9 :         iparam = makeNode(IndexElem);
                               1902                 : 
                               1903               9 :         if (AttributeNumberIsValid(attnum))
                               1904                 :         {
 1828 teodor                   1905 ECB             :             /* Simple index column */
                               1906                 :             char       *attname;
                               1907                 : 
 1828 teodor                   1908 CBC           9 :             attname = get_attname(indrelid, attnum, false);
 1828 teodor                   1909 ECB             : 
 1828 teodor                   1910 GIC           9 :             iparam->name = attname;
                               1911               9 :             iparam->expr = NULL;
                               1912                 :         }
                               1913                 :         else
 1828 teodor                   1914 UIC           0 :             ereport(ERROR,
                               1915                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1916                 :                      errmsg("expressions are not supported in included columns")));
 1828 teodor                   1917 ECB             : 
 1828 teodor                   1918 EUB             :         /* Copy the original index column name */
 1828 teodor                   1919 CBC           9 :         iparam->indexcolname = pstrdup(NameStr(attr->attname));
 1828 teodor                   1920 ECB             : 
 1828 teodor                   1921 GIC           9 :         index->indexIncludingParams = lappend(index->indexIncludingParams, iparam);
                               1922                 :     }
 5608 tgl                      1923 ECB             :     /* Copy reloptions if any */
 5608 tgl                      1924 GIC         759 :     datum = SysCacheGetAttr(RELOID, ht_idxrel,
                               1925                 :                             Anum_pg_class_reloptions, &isnull);
                               1926             759 :     if (!isnull)
 5608 tgl                      1927 UIC           0 :         index->options = untransformRelOptions(datum);
                               1928                 : 
 5745 neilc                    1929 ECB             :     /* If it's a partial index, decompile and append the predicate */
 5608 tgl                      1930 GBC         759 :     datum = SysCacheGetAttr(INDEXRELID, ht_idx,
                               1931                 :                             Anum_pg_index_indpred, &isnull);
 5608 tgl                      1932 GIC         759 :     if (!isnull)
                               1933                 :     {
                               1934                 :         char       *pred_str;
                               1935                 :         Node       *pred_tree;
 3935 tgl                      1936 ECB             :         bool        found_whole_row;
 5745 neilc                    1937                 : 
                               1938                 :         /* Convert text string to node tree */
 5493 tgl                      1939 CBC           9 :         pred_str = TextDatumGetCString(datum);
 3935 tgl                      1940 GIC           9 :         pred_tree = (Node *) stringToNode(pred_str);
                               1941                 : 
                               1942                 :         /* Adjust Vars to match new table's column numbering */
 3935 tgl                      1943 CBC           9 :         pred_tree = map_variable_attnos(pred_tree,
                               1944                 :                                         1, 0,
                               1945                 :                                         attmap,
 2075 rhaas                    1946 ECB             :                                         InvalidOid, &found_whole_row);
                               1947                 : 
                               1948                 :         /* As in expandTableLikeClause, reject whole-row variables */
 3935 tgl                      1949 CBC           9 :         if (found_whole_row)
 3935 tgl                      1950 LBC           0 :             ereport(ERROR,
 3935 tgl                      1951 ECB             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1952                 :                      errmsg("cannot convert whole-row table reference"),
 2118                          1953                 :                      errdetail("Index \"%s\" contains a whole-row table reference.",
                               1954                 :                                RelationGetRelationName(source_idx))));
                               1955                 : 
 3935 tgl                      1956 GIC           9 :         index->whereClause = pred_tree;
 5745 neilc                    1957 ECB             :     }
                               1958                 : 
                               1959                 :     /* Clean up */
 5745 neilc                    1960 GIC         759 :     ReleaseSysCache(ht_idxrel);
 2639 tgl                      1961             759 :     ReleaseSysCache(ht_am);
                               1962                 : 
 5745 neilc                    1963             759 :     return index;
                               1964                 : }
 5769 tgl                      1965 ECB             : 
                               1966                 : /*
 1861 alvherre                 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 *
 1861 alvherre                 1972 GIC          18 : generateClonedExtStatsStmt(RangeVar *heapRel, Oid heapRelid,
 1861 alvherre                 1973 ECB             :                            Oid source_statsid)
 1861 alvherre                 1974 EUB             : {
                               1975                 :     HeapTuple   ht_stats;
                               1976                 :     Form_pg_statistic_ext statsrec;
                               1977                 :     CreateStatsStmt *stats;
 1809 tgl                      1978 CBC          18 :     List       *stat_types = NIL;
 1809 tgl                      1979 GIC          18 :     List       *def_names = NIL;
                               1980                 :     bool        isnull;
                               1981                 :     Datum       datum;
 1809 tgl                      1982 ECB             :     ArrayType  *arr;
                               1983                 :     char       *enabled;
                               1984                 :     int         i;
 1861 alvherre                 1985                 : 
 1861 alvherre                 1986 CBC          18 :     Assert(OidIsValid(heapRelid));
 1861 alvherre                 1987 GIC          18 :     Assert(heapRel != NULL);
                               1988                 : 
 1861 alvherre                 1989 ECB             :     /*
                               1990                 :      * Fetch pg_statistic_ext tuple of source statistics object.
                               1991                 :      */
 1861 alvherre                 1992 GIC          18 :     ht_stats = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(source_statsid));
                               1993              18 :     if (!HeapTupleIsValid(ht_stats))
 1861 alvherre                 1994 UIC           0 :         elog(ERROR, "cache lookup failed for statistics object %u", source_statsid);
 1861 alvherre                 1995 GIC          18 :     statsrec = (Form_pg_statistic_ext) GETSTRUCT(ht_stats);
 1861 alvherre                 1996 ECB             : 
                               1997                 :     /* Determine which statistics types exist */
   15 dgustafsson              1998 GNC          18 :     datum = SysCacheGetAttrNotNull(STATEXTOID, ht_stats,
                               1999                 :                                    Anum_pg_statistic_ext_stxkind);
 1861 alvherre                 2000 GIC          18 :     arr = DatumGetArrayTypeP(datum);
 1861 alvherre                 2001 GBC          18 :     if (ARR_NDIM(arr) != 1 ||
 1861 alvherre                 2002 GIC          18 :         ARR_HASNULL(arr) ||
                               2003              18 :         ARR_ELEMTYPE(arr) != CHAROID)
 1861 alvherre                 2004 UIC           0 :         elog(ERROR, "stxkind is not a 1-D char array");
 1861 alvherre                 2005 GIC          18 :     enabled = (char *) ARR_DATA_PTR(arr);
 1861 alvherre                 2006 CBC          54 :     for (i = 0; i < ARR_DIMS(arr)[0]; i++)
                               2007                 :     {
                               2008              36 :         if (enabled[i] == STATS_EXT_NDISTINCT)
 1861 alvherre                 2009 GIC           9 :             stat_types = lappend(stat_types, makeString("ndistinct"));
                               2010              27 :         else if (enabled[i] == STATS_EXT_DEPENDENCIES)
 1861 alvherre                 2011 CBC           9 :             stat_types = lappend(stat_types, makeString("dependencies"));
 1474 tomas.vondra             2012 GIC          18 :         else if (enabled[i] == STATS_EXT_MCV)
 1474 tomas.vondra             2013 CBC           9 :             stat_types = lappend(stat_types, makeString("mcv"));
  744 tomas.vondra             2014 GBC           9 :         else if (enabled[i] == STATS_EXT_EXPRESSIONS)
                               2015                 :             /* expression stats are not exposed to users */
  744 tomas.vondra             2016 GIC           9 :             continue;
 1861 alvherre                 2017 ECB             :         else
 1861 alvherre                 2018 UIC           0 :             elog(ERROR, "unrecognized statistics kind %c", enabled[i]);
 1861 alvherre                 2019 ECB             :     }
                               2020                 : 
                               2021                 :     /* Determine which columns the statistics are on */
 1861 alvherre                 2022 GIC          36 :     for (i = 0; i < statsrec->stxkeys.dim1; i++)
                               2023                 :     {
  744 tomas.vondra             2024              18 :         StatsElem  *selem = makeNode(StatsElem);
 1861 alvherre                 2025              18 :         AttrNumber  attnum = statsrec->stxkeys.values[i];
 1861 alvherre                 2026 ECB             : 
  744 tomas.vondra             2027 CBC          18 :         selem->name = get_attname(heapRelid, attnum, false);
  744 tomas.vondra             2028 GIC          18 :         selem->expr = NULL;
                               2029                 : 
  744 tomas.vondra             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
  744 tomas.vondra             2036 ECB             :      * simply append them after simple column references.
  744 tomas.vondra             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                 :      */
  744 tomas.vondra             2042 GIC          18 :     datum = SysCacheGetAttr(STATEXTOID, ht_stats,
  744 tomas.vondra             2043 ECB             :                             Anum_pg_statistic_ext_stxexprs, &isnull);
                               2044                 : 
  744 tomas.vondra             2045 GIC          18 :     if (!isnull)
                               2046                 :     {
  744 tomas.vondra             2047 ECB             :         ListCell   *lc;
  744 tomas.vondra             2048 CBC           9 :         List       *exprs = NIL;
                               2049                 :         char       *exprsString;
  744 tomas.vondra             2050 ECB             : 
  744 tomas.vondra             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;
  744 tomas.vondra             2059 CBC           9 :             selem->expr = (Node *) lfirst(lc);
                               2060                 : 
  744 tomas.vondra             2061 GIC           9 :             def_names = lappend(def_names, selem);
                               2062                 :         }
                               2063                 : 
                               2064               9 :         pfree(exprsString);
 1861 alvherre                 2065 ECB             :     }
                               2066                 : 
                               2067                 :     /* finally, build the output node */
 1861 alvherre                 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);
 1861 alvherre                 2073 CBC          18 :     stats->stxcomment = NULL;
  744 tomas.vondra             2074              18 :     stats->transformed = true;   /* don't need transformStatsStmt again */
  668 noah                     2075 GIC          18 :     stats->if_not_exists = false;
                               2076                 : 
                               2077                 :     /* Clean up */
 1861 alvherre                 2078              18 :     ReleaseSysCache(ht_stats);
 1861 alvherre                 2079 ECB             : 
 1861 alvherre                 2080 CBC          18 :     return stats;
 1861 alvherre                 2081 EUB             : }
 1861 alvherre                 2082 ECB             : 
                               2083                 : /*
                               2084                 :  * get_collation        - fetch qualified name of a collation
 4397 tgl                      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 *
 4397 tgl                      2090 CBC         861 : get_collation(Oid collation, Oid actual_datatype)
 4397 tgl                      2091 EUB             : {
 4397 tgl                      2092 ECB             :     List       *result;
                               2093                 :     HeapTuple   ht_coll;
                               2094                 :     Form_pg_collation coll_rec;
                               2095                 :     char       *nsp_name;
                               2096                 :     char       *coll_name;
                               2097                 : 
 4397 tgl                      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));
 4397 tgl                      2104 GIC           3 :     if (!HeapTupleIsValid(ht_coll))
 4397 tgl                      2105 UBC           0 :         elog(ERROR, "cache lookup failed for collation %u", collation);
 4397 tgl                      2106 GIC           3 :     coll_rec = (Form_pg_collation) GETSTRUCT(ht_coll);
                               2107                 : 
                               2108                 :     /* For simplicity, we always schema-qualify the name */
 4397 tgl                      2109 CBC           3 :     nsp_name = get_namespace_name(coll_rec->collnamespace);
 4397 tgl                      2110 GIC           3 :     coll_name = pstrdup(NameStr(coll_rec->collname));
 4397 tgl                      2111 CBC           3 :     result = list_make2(makeString(nsp_name), makeString(coll_name));
 4397 tgl                      2112 ECB             : 
 4397 tgl                      2113 GIC           3 :     ReleaseSysCache(ht_coll);
 4397 tgl                      2114 CBC           3 :     return result;
 4397 tgl                      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 *
 5745 neilc                    2124 GIC         861 : get_opclass(Oid opclass, Oid actual_datatype)
                               2125                 : {
 4397 tgl                      2126             861 :     List       *result = NIL;
                               2127                 :     HeapTuple   ht_opc;
                               2128                 :     Form_pg_opclass opc_rec;
 5745 neilc                    2129 ECB             : 
 4802 rhaas                    2130 GIC         861 :     ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
 5745 neilc                    2131             861 :     if (!HeapTupleIsValid(ht_opc))
 5745 neilc                    2132 LBC           0 :         elog(ERROR, "cache lookup failed for opclass %u", opclass);
 5745 neilc                    2133 GIC         861 :     opc_rec = (Form_pg_opclass) GETSTRUCT(ht_opc);
                               2134                 : 
 5608 tgl                      2135 CBC         861 :     if (GetDefaultOpClass(actual_datatype, opc_rec->opcmethod) != opclass)
                               2136                 :     {
                               2137                 :         /* For simplicity, we always schema-qualify the name */
 5624 bruce                    2138               3 :         char       *nsp_name = get_namespace_name(opc_rec->opcnamespace);
 5608 tgl                      2139               3 :         char       *opc_name = pstrdup(NameStr(opc_rec->opcname));
                               2140                 : 
 5745 neilc                    2141               3 :         result = list_make2(makeString(nsp_name), makeString(opc_name));
                               2142                 :     }
 5745 neilc                    2143 ECB             : 
 5745 neilc                    2144 GIC         861 :     ReleaseSysCache(ht_opc);
 5745 neilc                    2145 CBC         861 :     return result;
 5745 neilc                    2146 ECB             : }
                               2147                 : 
                               2148                 : 
                               2149                 : /*
                               2150                 :  * transformIndexConstraints
 4871 tgl                      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                 :  */
 5745 neilc                    2155                 : static void
 4457 tgl                      2156 CBC       55506 : transformIndexConstraints(CreateStmtContext *cxt)
 5745 neilc                    2157 ECB             : {
                               2158                 :     IndexStmt  *index;
 5745 neilc                    2159 CBC       55506 :     List       *indexlist = NIL;
 1447 tgl                      2160           55506 :     List       *finalindexlist = NIL;
 5745 neilc                    2161 ECB             :     ListCell   *lc;
 5769 tgl                      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                 :      */
 5745 neilc                    2171 GIC       92557 :     foreach(lc, cxt->ixconstraints)
                               2172                 :     {
 2190 tgl                      2173           37057 :         Constraint *constraint = lfirst_node(Constraint, lc);
                               2174                 : 
 5608                          2175           37057 :         Assert(constraint->contype == CONSTR_PRIMARY ||
                               2176                 :                constraint->contype == CONSTR_UNIQUE ||
                               2177                 :                constraint->contype == CONSTR_EXCLUSION);
                               2178                 : 
 5745 neilc                    2179 CBC       37057 :         index = transformIndexConstraint(constraint, cxt);
                               2180                 : 
 5608 tgl                      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
 3602 bruce                    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
 5769 tgl                      2189                 :      *
                               2190                 :      * XXX in ALTER TABLE case, it'd be nice to look for duplicate
                               2191                 :      * pre-existing indexes, too.
                               2192                 :      */
 5769 tgl                      2193 CBC       55500 :     if (cxt->pkey != NULL)
 5769 tgl                      2194 EUB             :     {
 5769 tgl                      2195 ECB             :         /* Make sure we keep the PKEY index in preference to others... */
 1447 tgl                      2196 GIC       22076 :         finalindexlist = list_make1(cxt->pkey);
                               2197                 :     }
 5769 tgl                      2198 ECB             : 
 5745 neilc                    2199 CBC       92551 :     foreach(lc, indexlist)
 5769 tgl                      2200 ECB             :     {
 5769 tgl                      2201 GIC       37051 :         bool        keep = true;
 5769 tgl                      2202 ECB             :         ListCell   *k;
                               2203                 : 
 5745 neilc                    2204 GIC       37051 :         index = lfirst(lc);
                               2205                 : 
                               2206                 :         /* if it's pkey, it's already in finalindexlist */
 5769 tgl                      2207           37051 :         if (index == cxt->pkey)
                               2208           22076 :             continue;
                               2209                 : 
 1447                          2210           15050 :         foreach(k, finalindexlist)
                               2211                 :         {
 5769                          2212              75 :             IndexStmt  *priorindex = lfirst(k);
 5769 tgl                      2213 ECB             : 
 5608 tgl                      2214 GIC          78 :             if (equal(index->indexParams, priorindex->indexParams) &&
 1828 teodor                   2215 CBC           6 :                 equal(index->indexIncludingParams, priorindex->indexIncludingParams) &&
 5608 tgl                      2216 GIC           6 :                 equal(index->whereClause, priorindex->whereClause) &&
 4871                          2217               3 :                 equal(index->excludeOpNames, priorindex->excludeOpNames) &&
 5002                          2218               3 :                 strcmp(index->accessMethod, priorindex->accessMethod) == 0 &&
  430 peter                    2219 CBC           3 :                 index->nulls_not_distinct == priorindex->nulls_not_distinct &&
 5002 tgl                      2220               3 :                 index->deferrable == priorindex->deferrable &&
 5002 tgl                      2221 UBC           0 :                 index->initdeferred == priorindex->initdeferred)
 5769 tgl                      2222 ECB             :             {
 5608 tgl                      2223 UIC           0 :                 priorindex->unique |= index->unique;
 5050 bruce                    2224 ECB             : 
                               2225                 :                 /*
                               2226                 :                  * If the prior index is as yet unnamed, and this one is
 5769 tgl                      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                 :                  */
 5769 tgl                      2231 UIC           0 :                 if (priorindex->idxname == NULL)
                               2232               0 :                     priorindex->idxname = index->idxname;
 5769 tgl                      2233 LBC           0 :                 keep = false;
                               2234               0 :                 break;
                               2235                 :             }
                               2236                 :         }
                               2237                 : 
 5769 tgl                      2238 GIC       14975 :         if (keep)
 1447                          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);
 5745 neilc                    2246 CBC       55500 : }
 5745 neilc                    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 *
 5745 neilc                    2257 GIC       37057 : transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
 5745 neilc                    2258 ECB             : {
                               2259                 :     IndexStmt  *index;
 1447 tgl                      2260 CBC       37057 :     List       *notnullcmds = NIL;
                               2261                 :     ListCell   *lc;
                               2262                 : 
 5745 neilc                    2263 GIC       37057 :     index = makeNode(IndexStmt);
 5608 tgl                      2264 ECB             : 
 4871 tgl                      2265 GIC       37057 :     index->unique = (constraint->contype != CONSTR_EXCLUSION);
 5745 neilc                    2266 CBC       37057 :     index->primary = (constraint->contype == CONSTR_PRIMARY);
 5745 neilc                    2267 GIC       37057 :     if (index->primary)
                               2268                 :     {
                               2269           22076 :         if (cxt->pkey != NULL)
 5745 neilc                    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)));
 5745 neilc                    2275 GIC       22076 :         cxt->pkey = index;
                               2276                 : 
                               2277                 :         /*
 5745 neilc                    2278 ECB             :          * In ALTER TABLE case, a primary index might already exist, but
                               2279                 :          * DefineIndex will check for it.
                               2280                 :          */
                               2281                 :     }
  430 peter                    2282 GIC       37057 :     index->nulls_not_distinct = constraint->nulls_not_distinct;
 5745 neilc                    2283           37057 :     index->isconstraint = true;
 5002 tgl                      2284 CBC       37057 :     index->deferrable = constraint->deferrable;
 5002 tgl                      2285 GIC       37057 :     index->initdeferred = constraint->initdeferred;
 5745 neilc                    2286 ECB             : 
 5001 tgl                      2287 GIC       37057 :     if (constraint->conname != NULL)
                               2288             426 :         index->idxname = pstrdup(constraint->conname);
 5745 neilc                    2289 ECB             :     else
 5624 bruce                    2290 GIC       36631 :         index->idxname = NULL;   /* DefineIndex will choose name */
                               2291                 : 
 5745 neilc                    2292 CBC       37057 :     index->relation = cxt->relation;
 4871 tgl                      2293           37057 :     index->accessMethod = constraint->access_method ? constraint->access_method : DEFAULT_INDEX_TYPE;
 5745 neilc                    2294 GIC       37057 :     index->options = constraint->options;
 5745 neilc                    2295 CBC       37057 :     index->tableSpace = constraint->indexspace;
 4871 tgl                      2296 GIC       37057 :     index->whereClause = constraint->where_clause;
 5745 neilc                    2297 CBC       37057 :     index->indexParams = NIL;
 1828 teodor                   2298 GIC       37057 :     index->indexIncludingParams = NIL;
 4871 tgl                      2299 CBC       37057 :     index->excludeOpNames = NIL;
 3919                          2300           37057 :     index->idxcomment = NULL;
 4457                          2301           37057 :     index->indexOid = InvalidOid;
  277 rhaas                    2302 GNC       37057 :     index->oldNumber = InvalidRelFileNumber;
 1100 noah                     2303 CBC       37057 :     index->oldCreateSubid = InvalidSubTransactionId;
  277 rhaas                    2304 GNC       37057 :     index->oldFirstRelfilelocatorSubid = InvalidSubTransactionId;
 2968 tgl                      2305 CBC       37057 :     index->transformed = false;
 5745 neilc                    2306 GBC       37057 :     index->concurrent = false;
 2968 tgl                      2307 GIC       37057 :     index->if_not_exists = false;
 1445 alvherre                 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                 :      */
 4457 tgl                      2316           37057 :     if (constraint->indexname != NULL)
 4457 tgl                      2317 EUB             :     {
 4457 tgl                      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;
 4457 tgl                      2323 ECB             :         oidvector  *indclass;
                               2324                 :         Datum       indclassDatum;
                               2325                 :         int         i;
                               2326                 : 
                               2327                 :         /* Grammar should not allow this with explicit column list */
 4457 tgl                      2328 GIC       33367 :         Assert(constraint->keys == NIL);
 4457 tgl                      2329 ECB             : 
                               2330                 :         /* Grammar should only allow PRIMARY and UNIQUE constraints */
 4457 tgl                      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)
 4457 tgl                      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                 : 
 4457 tgl                      2341 ECB             :         /* Look for the index in the same schema as the table */
 4457 tgl                      2342 GIC       33367 :         index_oid = get_relname_relid(index_name, RelationGetNamespace(heap_rel));
                               2343                 : 
 4457 tgl                      2344 CBC       33367 :         if (!OidIsValid(index_oid))
 4457 tgl                      2345 UIC           0 :             ereport(ERROR,
                               2346                 :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
 4457 tgl                      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) */
 4457 tgl                      2351 CBC       33367 :         index_rel = index_open(index_oid, AccessShareLock);
 4457 tgl                      2352 GIC       33367 :         index_form = index_rel->rd_index;
 4457 tgl                      2353 ECB             : 
 4457 tgl                      2354 EUB             :         /* Check that it does not have an associated constraint already */
 4457 tgl                      2355 GIC       33367 :         if (OidIsValid(get_index_constraint(index_oid)))
 4457 tgl                      2356 UIC           0 :             ereport(ERROR,
                               2357                 :                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                               2358                 :                      errmsg("index \"%s\" is already associated with a constraint",
 2118 tgl                      2359 ECB             :                             index_name),
                               2360                 :                      parser_errposition(cxt->pstate, constraint->location)));
                               2361                 : 
                               2362                 :         /* Perform validity checks on the index */
 4457 tgl                      2363 GIC       33367 :         if (index_form->indrelid != RelationGetRelid(heap_rel))
 4457 tgl                      2364 UIC           0 :             ereport(ERROR,
                               2365                 :                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 4457 tgl                      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                 : 
 1564 peter_e                  2370 GIC       33367 :         if (!index_form->indisvalid)
 4457 tgl                      2371 LBC           0 :             ereport(ERROR,
 4457 tgl                      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                 : 
 4457 tgl                      2376 CBC       33367 :         if (!index_form->indisunique)
 4457 tgl                      2377 LBC           0 :             ereport(ERROR,
 4457 tgl                      2378 ECB             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                               2379                 :                      errmsg("\"%s\" is not a unique index", index_name),
 4309 peter_e                  2380                 :                      errdetail("Cannot create a primary key or unique constraint using such an index."),
 4457 tgl                      2381                 :                      parser_errposition(cxt->pstate, constraint->location)));
                               2382                 : 
 4457 tgl                      2383 CBC       33367 :         if (RelationGetIndexExpressions(index_rel) != NIL)
 4457 tgl                      2384 LBC           0 :             ereport(ERROR,
 4457 tgl                      2385 ECB             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                               2386                 :                      errmsg("index \"%s\" contains expressions", index_name),
 4309 peter_e                  2387                 :                      errdetail("Cannot create a primary key or unique constraint using such an index."),
 4457 tgl                      2388                 :                      parser_errposition(cxt->pstate, constraint->location)));
                               2389                 : 
 4457 tgl                      2390 CBC       33367 :         if (RelationGetIndexPredicate(index_rel) != NIL)
 4457 tgl                      2391 LBC           0 :             ereport(ERROR,
 4457 tgl                      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                 :          */
 4457 tgl                      2402 CBC       33367 :         if (!index_form->indimmediate && !constraint->deferrable)
 4457 tgl                      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
 4457 tgl                      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                 :          */
 2573 alvherre                 2416 GIC       33367 :         if (index_rel->rd_rel->relam != get_index_am_oid(DEFAULT_INDEX_TYPE, false))
 4457 tgl                      2417 UIC           0 :             ereport(ERROR,
                               2418                 :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
 4296 peter_e                  2419 ECB             :                      errmsg("index \"%s\" is not a btree", index_name),
 4457 tgl                      2420 EUB             :                      parser_errposition(cxt->pstate, constraint->location)));
                               2421                 : 
                               2422                 :         /* Must get indclass the hard way */
   15 dgustafsson              2423 GNC       33367 :         indclassDatum = SysCacheGetAttrNotNull(INDEXRELID,
                               2424           33367 :                                                index_rel->rd_indextuple,
                               2425                 :                                                Anum_pg_index_indclass);
 4457 tgl                      2426 CBC       33367 :         indclass = (oidvector *) DatumGetPointer(indclassDatum);
                               2427                 : 
                               2428           88271 :         for (i = 0; i < index_form->indnatts; i++)
 4457 tgl                      2429 EUB             :         {
 3940 peter_e                  2430 GIC       54910 :             int16       attnum = index_form->indkey.values[i];
                               2431                 :             const FormData_pg_attribute *attform;
                               2432                 :             char       *attname;
                               2433                 :             Oid         defopclass;
                               2434                 : 
 4457 tgl                      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                 :              */
 4457 tgl                      2440 GBC       54910 :             if (attnum > 0)
                               2441                 :             {
 4457 tgl                      2442 GIC       54910 :                 Assert(attnum <= heap_rel->rd_att->natts);
 2058 andres                   2443           54910 :                 attform = TupleDescAttr(heap_rel->rd_att, attnum - 1);
                               2444                 :             }
                               2445                 :             else
 1601 andres                   2446 UIC           0 :                 attform = SystemAttributeDefinition(attnum);
 4457 tgl                      2447 CBC       54910 :             attname = pstrdup(NameStr(attform->attname));
 4457 tgl                      2448 EUB             : 
 1828 teodor                   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
 1220 tgl                      2454 ECB             :                  * non-default settings, it might not provide exactly the same
 1220 tgl                      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 =
 1060 tgl                      2460 CBC       54895 :                 get_attoptions(RelationGetRelid(index_rel), i + 1);
 1105 akorotkov                2461 EUB             : 
 1828 teodor                   2462 GIC       54895 :                 defopclass = GetDefaultOpClass(attform->atttypid,
                               2463           54895 :                                                index_rel->rd_rel->relam);
                               2464           54895 :                 if (indclass->values[i] != defopclass ||
 1220 tgl                      2465           54895 :                     attform->attcollation != index_rel->rd_indcollation[i] ||
 1105 akorotkov                2466           54892 :                     attoptions != (Datum) 0 ||
 1828 teodor                   2467 CBC       54892 :                     index_rel->rd_indoption[i] != 0)
 1828 teodor                   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                 : 
 1828 teodor                   2474 CBC       54889 :                 constraint->keys = lappend(constraint->keys, makeString(attname));
 1828 teodor                   2475 EUB             :             }
                               2476                 :             else
 1828 teodor                   2477 GIC          15 :                 constraint->including = lappend(constraint->including, makeString(attname));
                               2478                 :         }
                               2479                 : 
                               2480                 :         /* Close the index relation but keep the lock */
 4457 tgl                      2481           33361 :         relation_close(index_rel, NoLock);
                               2482                 : 
                               2483           33361 :         index->indexOid = index_oid;
                               2484                 :     }
                               2485                 : 
 5745 neilc                    2486 ECB             :     /*
 4790 bruce                    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                 :      */
 4871 tgl                      2491 GIC       37051 :     if (constraint->contype == CONSTR_EXCLUSION)
                               2492                 :     {
                               2493             143 :         foreach(lc, constraint->exclusions)
                               2494                 :         {
 4790 bruce                    2495              79 :             List       *pair = (List *) lfirst(lc);
                               2496                 :             IndexElem  *elem;
                               2497                 :             List       *opname;
                               2498                 : 
 4871 tgl                      2499              79 :             Assert(list_length(pair) == 2);
 2190 tgl                      2500 CBC          79 :             elem = linitial_node(IndexElem, pair);
 2190 tgl                      2501 GBC          79 :             opname = lsecond_node(List, pair);
                               2502                 : 
 4871 tgl                      2503 GIC          79 :             index->indexParams = lappend(index->indexParams, elem);
                               2504              79 :             index->excludeOpNames = lappend(index->excludeOpNames, opname);
                               2505                 :         }
                               2506                 :     }
 4871 tgl                      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,
 1447                          2512                 :      * also make sure they are NOT NULL.
                               2513                 :      */
 1828 teodor                   2514                 :     else
                               2515                 :     {
 1828 teodor                   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;
 1828 teodor                   2523 ECB             : 
                               2524                 :             /* Make sure referenced column exists. */
 1828 teodor                   2525 CBC       59469 :             foreach(columns, cxt->columns)
 1828 teodor                   2526 ECB             :             {
  629 peter                    2527 GIC        3950 :                 column = lfirst_node(ColumnDef, columns);
 1828 teodor                   2528            3950 :                 if (strcmp(column->colname, key) == 0)
 1828 teodor                   2529 EUB             :                 {
 1828 teodor                   2530 CBC        3412 :                     found = true;
 1828 teodor                   2531 GIC        3412 :                     break;
 1828 teodor                   2532 ECB             :                 }
                               2533                 :             }
 1828 teodor                   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                 :                  */
 1447 tgl                      2544            3412 :                 if (constraint->contype == CONSTR_PRIMARY &&
 1447 tgl                      2545 CBC        3138 :                     !column->is_from_type)
                               2546                 :                 {
 1828 teodor                   2547            3125 :                     column->is_not_null = true;
 1447 tgl                      2548 ECB             :                 }
 1828 teodor                   2549                 :             }
 1601 andres                   2550 CBC       55519 :             else if (SystemAttributeByName(key) != NULL)
 1828 teodor                   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                 :                  */
 1828 teodor                   2557 UIC           0 :                 found = true;
 1828 teodor                   2558 ECB             :             }
 1828 teodor                   2559 GIC       55519 :             else if (cxt->inhRelations)
                               2560                 :             {
 1828 teodor                   2561 ECB             :                 /* try inherited tables */
                               2562                 :                 ListCell   *inher;
                               2563                 : 
 1828 teodor                   2564 GIC          30 :                 foreach(inher, cxt->inhRelations)
 1828 teodor                   2565 ECB             :                 {
  629 peter                    2566 GIC          30 :                     RangeVar   *inh = lfirst_node(RangeVar, inher);
 1828 teodor                   2567 ECB             :                     Relation    rel;
                               2568                 :                     int         count;
                               2569                 : 
 1539 andres                   2570 GIC          30 :                     rel = table_openrv(inh, AccessShareLock);
                               2571                 :                     /* check user requested inheritance from valid relkind */
 1828 teodor                   2572              30 :                     if (rel->rd_rel->relkind != RELKIND_RELATION &&
 1828 teodor                   2573 UIC           0 :                         rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
                               2574               0 :                         rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
 1828 teodor                   2575 LBC           0 :                         ereport(ERROR,
                               2576                 :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
 1828 teodor                   2577 ECB             :                                  errmsg("inherited relation \"%s\" is not a table or foreign table",
                               2578                 :                                         inh->relname)));
 1828 teodor                   2579 CBC          30 :                     for (count = 0; count < rel->rd_att->natts; count++)
                               2580                 :                     {
 1828 teodor                   2581 GIC          30 :                         Form_pg_attribute inhattr = TupleDescAttr(rel->rd_att,
                               2582                 :                                                                   count);
 1828 teodor                   2583 CBC          30 :                         char       *inhname = NameStr(inhattr->attname);
 1828 teodor                   2584 ECB             : 
 1828 teodor                   2585 CBC          30 :                         if (inhattr->attisdropped)
 1828 teodor                   2586 UIC           0 :                             continue;
 1828 teodor                   2587 CBC          30 :                         if (strcmp(key, inhname) == 0)
 1828 teodor                   2588 ECB             :                         {
 1828 teodor                   2589 GIC          30 :                             found = true;
                               2590              30 :                             break;
                               2591                 :                         }
 1828 teodor                   2592 ECB             :                     }
 1539 andres                   2593 GIC          30 :                     table_close(rel, NoLock);
 1828 teodor                   2594 CBC          30 :                     if (found)
                               2595              30 :                         break;
 1828 teodor                   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                 :              */
 1828 teodor                   2604 CBC       58931 :             if (!found && !cxt->isalter)
 1828 teodor                   2605 UIC           0 :                 ereport(ERROR,
 1828 teodor                   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) */
 1828 teodor                   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                 :                 {
 1828 teodor                   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",
 1828 teodor                   2620 ECB             :                                         key),
                               2621                 :                                  parser_errposition(cxt->pstate, constraint->location)));
                               2622                 :                     else
 1828 teodor                   2623 LBC           0 :                         ereport(ERROR,
                               2624                 :                                 (errcode(ERRCODE_DUPLICATE_COLUMN),
                               2625                 :                                  errmsg("column \"%s\" appears twice in unique constraint",
 1828 teodor                   2626 ECB             :                                         key),
                               2627                 :                                  parser_errposition(cxt->pstate, constraint->location)));
                               2628                 :                 }
                               2629                 :             }
                               2630                 : 
                               2631                 :             /* OK, add it to the index definition */
 1828 teodor                   2632 GIC       58931 :             iparam = makeNode(IndexElem);
 1828 teodor                   2633 GBC       58931 :             iparam->name = pstrdup(key);
 1828 teodor                   2634 GIC       58931 :             iparam->expr = NULL;
 1828 teodor                   2635 CBC       58931 :             iparam->indexcolname = NULL;
 1828 teodor                   2636 GIC       58931 :             iparam->collation = NIL;
                               2637           58931 :             iparam->opclass = NIL;
 1105 akorotkov                2638           58931 :             iparam->opclassopts = NIL;
 1828 teodor                   2639           58931 :             iparam->ordering = SORTBY_DEFAULT;
 1828 teodor                   2640 CBC       58931 :             iparam->nulls_ordering = SORTBY_NULLS_DEFAULT;
 1828 teodor                   2641 GIC       58931 :             index->indexParams = lappend(index->indexParams, iparam);
 1447 tgl                      2642 ECB             : 
    2 alvherre                 2643 GNC       58931 :             if (constraint->contype == CONSTR_PRIMARY)
 1447 tgl                      2644 ECB             :             {
 1447 tgl                      2645 GBC       28454 :                 AlterTableCmd *notnullcmd = makeNode(AlterTableCmd);
 1447 tgl                      2646 EUB             : 
    2 alvherre                 2647 GNC       28454 :                 notnullcmd->subtype = AT_SetAttNotNull;
 1447 tgl                      2648 GIC       28454 :                 notnullcmd->name = pstrdup(key);
                               2649           28454 :                 notnullcmds = lappend(notnullcmds, notnullcmd);
                               2650                 :             }
 1828 teodor                   2651 ECB             :         }
                               2652                 :     }
                               2653                 : 
                               2654                 :     /*
 1447 tgl                      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
 1447 tgl                      2658 EUB             :      * forced NOT NULL.  We don't complain about duplicate columns, either,
 1447 tgl                      2659 ECB             :      * though maybe we should?
                               2660                 :      */
 1828 teodor                   2661 CBC       37205 :     foreach(lc, constraint->including)
 5745 neilc                    2662 ECB             :     {
 4871 tgl                      2663 GIC         154 :         char       *key = strVal(lfirst(lc));
 5745 neilc                    2664             154 :         bool        found = false;
 5745 neilc                    2665 CBC         154 :         ColumnDef  *column = NULL;
 5745 neilc                    2666 ECB             :         ListCell   *columns;
 4871 tgl                      2667                 :         IndexElem  *iparam;
                               2668                 : 
 5745 neilc                    2669 GIC         331 :         foreach(columns, cxt->columns)
                               2670                 :         {
 2190 tgl                      2671             272 :             column = lfirst_node(ColumnDef, columns);
 5745 neilc                    2672             272 :             if (strcmp(column->colname, key) == 0)
                               2673                 :             {
                               2674              95 :                 found = true;
                               2675              95 :                 break;
 5745 neilc                    2676 ECB             :             }
 5745 neilc                    2677 EUB             :         }
                               2678                 : 
 1828 teodor                   2679 GIC         154 :         if (!found)
                               2680                 :         {
 1601 andres                   2681              59 :             if (SystemAttributeByName(key) != NULL)
                               2682                 :             {
 1828 teodor                   2683 ECB             :                 /*
                               2684                 :                  * column will be a system column in the new table, so accept
 1447 tgl                      2685                 :                  * it.
 1828 teodor                   2686                 :                  */
 1828 teodor                   2687 UIC           0 :                 found = true;
 1828 teodor                   2688 EUB             :             }
 1828 teodor                   2689 GBC          59 :             else if (cxt->inhRelations)
                               2690                 :             {
                               2691                 :                 /* try inherited tables */
                               2692                 :                 ListCell   *inher;
                               2693                 : 
 1828 teodor                   2694 UIC           0 :                 foreach(inher, cxt->inhRelations)
 1828 teodor                   2695 EUB             :                 {
 1828 teodor                   2696 UIC           0 :                     RangeVar   *inh = lfirst_node(RangeVar, inher);
                               2697                 :                     Relation    rel;
                               2698                 :                     int         count;
                               2699                 : 
 1539 andres                   2700               0 :                     rel = table_openrv(inh, AccessShareLock);
                               2701                 :                     /* check user requested inheritance from valid relkind */
 1828 teodor                   2702               0 :                     if (rel->rd_rel->relkind != RELKIND_RELATION &&
                               2703               0 :                         rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
 1828 teodor                   2704 LBC           0 :                         rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
                               2705               0 :                         ereport(ERROR,
 1828 teodor                   2706 ECB             :                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                               2707                 :                                  errmsg("inherited relation \"%s\" is not a table or foreign table",
                               2708                 :                                         inh->relname)));
 1828 teodor                   2709 LBC           0 :                     for (count = 0; count < rel->rd_att->natts; count++)
 5745 neilc                    2710 ECB             :                     {
 1828 teodor                   2711 LBC           0 :                         Form_pg_attribute inhattr = TupleDescAttr(rel->rd_att,
 1828 teodor                   2712 ECB             :                                                                   count);
 1828 teodor                   2713 LBC           0 :                         char       *inhname = NameStr(inhattr->attname);
                               2714                 : 
                               2715               0 :                         if (inhattr->attisdropped)
 1828 teodor                   2716 UIC           0 :                             continue;
 1828 teodor                   2717 LBC           0 :                         if (strcmp(key, inhname) == 0)
                               2718                 :                         {
                               2719               0 :                             found = true;
                               2720               0 :                             break;
 1828 teodor                   2721 ECB             :                         }
                               2722                 :                     }
 1539 andres                   2723 UIC           0 :                     table_close(rel, NoLock);
 1828 teodor                   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
 1447 tgl                      2733 ECB             :          * will complain about them if not.
                               2734                 :          */
 5745 neilc                    2735 CBC         154 :         if (!found && !cxt->isalter)
 5745 neilc                    2736 LBC           0 :             ereport(ERROR,
 5745 neilc                    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 */
 5745 neilc                    2742 GIC         154 :         iparam = makeNode(IndexElem);
 5745 neilc                    2743 CBC         154 :         iparam->name = pstrdup(key);
                               2744             154 :         iparam->expr = NULL;
 4855 tgl                      2745 GIC         154 :         iparam->indexcolname = NULL;
 4397 tgl                      2746 CBC         154 :         iparam->collation = NIL;
 5745 neilc                    2747             154 :         iparam->opclass = NIL;
 1105 akorotkov                2748 GIC         154 :         iparam->opclassopts = NIL;
 1828 teodor                   2749             154 :         index->indexIncludingParams = lappend(index->indexIncludingParams, iparam);
                               2750                 :     }
 5745 neilc                    2751 ECB             : 
                               2752                 :     /*
 1447 tgl                      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                 :      */
 1447 tgl                      2756 GIC       37051 :     if (notnullcmds)
                               2757                 :     {
                               2758           22076 :         AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
 1447 tgl                      2759 EUB             : 
 1447 tgl                      2760 GIC       22076 :         alterstmt->relation = copyObject(cxt->relation);
 1447 tgl                      2761 CBC       22076 :         alterstmt->cmds = notnullcmds;
 1002 michael                  2762 GIC       22076 :         alterstmt->objtype = OBJECT_TABLE;
 1447 tgl                      2763           22076 :         alterstmt->missing_ok = false;
                               2764                 : 
                               2765           22076 :         cxt->alist = lappend(cxt->alist, alterstmt);
 1447 tgl                      2766 EUB             :     }
                               2767                 : 
 5745 neilc                    2768 GBC       37051 :     return index;
                               2769                 : }
                               2770                 : 
                               2771                 : /*
 1861 alvherre                 2772 EUB             :  * transformExtendedStatistics
                               2773                 :  *     Handle extended statistic objects
                               2774                 :  *
 1860                          2775                 :  * Right now, there's nothing to do here, so we just append the list to
                               2776                 :  * the existing "after" list.
 1861                          2777                 :  */
                               2778                 : static void
 1861 alvherre                 2779 GIC       55500 : transformExtendedStatistics(CreateStmtContext *cxt)
                               2780                 : {
 1861 alvherre                 2781 GBC       55500 :     cxt->alist = list_concat(cxt->alist, cxt->extstats);
 1861 alvherre                 2782 GIC       55500 : }
 1861 alvherre                 2783 EUB             : 
                               2784                 : /*
 2671 rhaas                    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
 2671 rhaas                    2794 GIC       55500 : transformCheckConstraints(CreateStmtContext *cxt, bool skipValidation)
 2671 rhaas                    2795 EUB             : {
                               2796                 :     ListCell   *ckclist;
                               2797                 : 
 2671 rhaas                    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)
 2671 rhaas                    2807 ECB             :     {
 2671 rhaas                    2808 GBC         598 :         foreach(ckclist, cxt->ckconstraints)
                               2809                 :         {
 2671 rhaas                    2810 GIC         325 :             Constraint *constraint = (Constraint *) lfirst(ckclist);
                               2811                 : 
                               2812             325 :             constraint->skip_validation = true;
                               2813             325 :             constraint->initially_valid = true;
 2671 rhaas                    2814 ECB             :         }
                               2815                 :     }
                               2816                 : }
                               2817                 : 
 5769 tgl                      2818                 : /*
                               2819                 :  * transformFKConstraints
                               2820                 :  *      handle FOREIGN KEY constraints
                               2821                 :  */
                               2822                 : static void
 4457 tgl                      2823 GIC       55500 : transformFKConstraints(CreateStmtContext *cxt,
                               2824                 :                        bool skipValidation, bool isAddConstraint)
                               2825                 : {
                               2826                 :     ListCell   *fkclist;
                               2827                 : 
 5769 tgl                      2828 CBC       55500 :     if (cxt->fkconstraints == NIL)
 5769 tgl                      2829 GIC       53931 :         return;
 5769 tgl                      2830 ECB             : 
                               2831                 :     /*
                               2832                 :      * If CREATE TABLE or adding a column with NULL default, we can safely
 4316                          2833                 :      * skip validation of FK constraints, and nonetheless mark them valid.
                               2834                 :      * (This will override any user-supplied NOT VALID flag.)
 5769                          2835                 :      */
 5769 tgl                      2836 GIC        1569 :     if (skipValidation)
 5769 tgl                      2837 ECB             :     {
 5769 tgl                      2838 GIC        1109 :         foreach(fkclist, cxt->fkconstraints)
                               2839                 :         {
 5001 tgl                      2840 CBC         570 :             Constraint *constraint = (Constraint *) lfirst(fkclist);
                               2841                 : 
 5001 tgl                      2842 GIC         570 :             constraint->skip_validation = true;
 4382 bruce                    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
 5769 tgl                      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                 :      */
 5769 tgl                      2858 GIC        1569 :     if (!isAddConstraint)
                               2859                 :     {
                               2860             536 :         AlterTableStmt *alterstmt = makeNode(AlterTableStmt);
                               2861                 : 
                               2862             536 :         alterstmt->relation = cxt->relation;
                               2863             536 :         alterstmt->cmds = NIL;
 1002 michael                  2864             536 :         alterstmt->objtype = OBJECT_TABLE;
                               2865                 : 
 5769 tgl                      2866 CBC        1103 :         foreach(fkclist, cxt->fkconstraints)
                               2867                 :         {
 5001 tgl                      2868 GIC         567 :             Constraint *constraint = (Constraint *) lfirst(fkclist);
 5769                          2869             567 :             AlterTableCmd *altercmd = makeNode(AlterTableCmd);
 5769 tgl                      2870 ECB             : 
 1180 tgl                      2871 CBC         567 :             altercmd->subtype = AT_AddConstraint;
 5769 tgl                      2872 GIC         567 :             altercmd->name = NULL;
 5001                          2873             567 :             altercmd->def = (Node *) constraint;
 5769                          2874             567 :             alterstmt->cmds = lappend(alterstmt->cmds, altercmd);
                               2875                 :         }
                               2876                 : 
                               2877             536 :         cxt->alist = lappend(cxt->alist, alterstmt);
 5769 tgl                      2878 ECB             :     }
                               2879                 : }
                               2880                 : 
                               2881                 : /*
 4638 simon                    2882                 :  * transformIndexStmt - parse analysis for CREATE INDEX and ALTER TABLE
                               2883                 :  *
 5769 tgl                      2884                 :  * Note: this is a no-op for an index not using either index expressions or
 3260 bruce                    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 *
 3338 rhaas                    2894 GIC       39881 : transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
 5769 tgl                      2895 ECB             : {
                               2896                 :     ParseState *pstate;
                               2897                 :     ParseNamespaceItem *nsitem;
                               2898                 :     ListCell   *l;
                               2899                 :     Relation    rel;
                               2900                 : 
 2968                          2901                 :     /* Nothing to do if statement already transformed. */
 2968 tgl                      2902 GIC       39881 :     if (stmt->transformed)
                               2903              56 :         return stmt;
                               2904                 : 
                               2905                 :     /* Set up pstate */
 5769                          2906           39825 :     pstate = make_parsestate(NULL);
                               2907           39825 :     pstate->p_sourcetext = queryString;
 5769 tgl                      2908 ECB             : 
                               2909                 :     /*
 5624 bruce                    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
 3338 rhaas                    2912                 :      * relation, but we still need to open it.
                               2913                 :      */
 3338 rhaas                    2914 CBC       39825 :     rel = relation_open(relid, NoLock);
 1193 tgl                      2915           39825 :     nsitem = addRangeTableEntryForRelation(pstate, rel,
                               2916                 :                                            AccessShareLock,
                               2917                 :                                            NULL, false, true);
                               2918                 : 
                               2919                 :     /* no to join list, yes to namespaces */
 1193 tgl                      2920 GIC       39825 :     addNSItemToQuery(pstate, nsitem, false, true, true);
                               2921                 : 
                               2922                 :     /* take care of the where clause */
 5769                          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 */
 4385 tgl                      2930 CBC         175 :         assign_expr_collations(pstate, stmt->whereClause);
                               2931                 :     }
 5769 tgl                      2932 ECB             : 
                               2933                 :     /* take care of any index expressions */
 5769 tgl                      2934 CBC      102372 :     foreach(l, stmt->indexParams)
 5769 tgl                      2935 ECB             :     {
 5769 tgl                      2936 CBC       62556 :         IndexElem  *ielem = (IndexElem *) lfirst(l);
                               2937                 : 
                               2938           62556 :         if (ielem->expr)
                               2939                 :         {
 4855 tgl                      2940 ECB             :             /* Extract preliminary index col name before transforming expr */
 4855 tgl                      2941 CBC         306 :             if (ielem->indexcolname == NULL)
 4855 tgl                      2942 GIC         306 :                 ielem->indexcolname = FigureIndexColname(ielem->expr);
 4855 tgl                      2943 ECB             : 
                               2944                 :             /* Now do parse transformation of the expression */
 3894 tgl                      2945 CBC         306 :             ielem->expr = transformExpr(pstate, ielem->expr,
 3894 tgl                      2946 ECB             :                                         EXPR_KIND_INDEX_EXPRESSION);
                               2947                 : 
                               2948                 :             /* We have to fix its collations too */
 4404 tgl                      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                 :      */
 5769 tgl                      2965 GIC       39816 :     if (list_length(pstate->p_rtable) != 1)
 5769 tgl                      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                 : 
 5769 tgl                      2970 GIC       39816 :     free_parsestate(pstate);
                               2971                 : 
                               2972                 :     /* Close relation */
 1539 andres                   2973           39816 :     table_close(rel, NoLock);
 5769 tgl                      2974 ECB             : 
 2968                          2975                 :     /* Mark statement as successfully transformed */
 2968 tgl                      2976 GIC       39816 :     stmt->transformed = true;
                               2977                 : 
 5769 tgl                      2978 CBC       39816 :     return stmt;
 5769 tgl                      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
  744 tomas.vondra             2986                 :  * relation.
                               2987                 :  */
                               2988                 : CreateStatsStmt *
  744 tomas.vondra             2989 GIC         295 : transformStatsStmt(Oid relid, CreateStatsStmt *stmt, const char *queryString)
                               2990                 : {
                               2991                 :     ParseState *pstate;
  744 tomas.vondra             2992 ECB             :     ParseNamespaceItem *nsitem;
                               2993                 :     ListCell   *l;
                               2994                 :     Relation    rel;
                               2995                 : 
                               2996                 :     /* Nothing to do if statement already transformed. */
  744 tomas.vondra             2997 CBC         295 :     if (stmt->transformed)
  744 tomas.vondra             2998 GIC          18 :         return stmt;
                               2999                 : 
                               3000                 :     /* Set up pstate */
                               3001             277 :     pstate = make_parsestate(NULL);
  744 tomas.vondra             3002 CBC         277 :     pstate->p_sourcetext = queryString;
                               3003                 : 
                               3004                 :     /*
                               3005                 :      * Put the parent table into the rtable so that the expressions can refer
  744 tomas.vondra             3006 ECB             :      * to its fields without qualification.  Caller is responsible for locking
                               3007                 :      * relation, but we still need to open it.
                               3008                 :      */
  744 tomas.vondra             3009 GIC         277 :     rel = relation_open(relid, NoLock);
  744 tomas.vondra             3010 CBC         277 :     nsitem = addRangeTableEntryForRelation(pstate, rel,
                               3011                 :                                            AccessShareLock,
                               3012                 :                                            NULL, false, true);
  744 tomas.vondra             3013 ECB             : 
                               3014                 :     /* no to join list, yes to namespaces */
  744 tomas.vondra             3015 GIC         277 :     addNSItemToQuery(pstate, nsitem, false, true, true);
                               3016                 : 
  744 tomas.vondra             3017 ECB             :     /* take care of any expressions */
  744 tomas.vondra             3018 GIC        1009 :     foreach(l, stmt->exprs)
                               3019                 :     {
                               3020             732 :         StatsElem  *selem = (StatsElem *) lfirst(l);
  744 tomas.vondra             3021 ECB             : 
  744 tomas.vondra             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                 :      */
  744 tomas.vondra             3037 CBC         277 :     if (list_length(pstate->p_rtable) != 1)
  744 tomas.vondra             3038 UBC           0 :         ereport(ERROR,
                               3039                 :                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                               3040                 :                  errmsg("statistics expressions can refer only to the table being referenced")));
                               3041                 : 
  744 tomas.vondra             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
 5769 tgl                      3061 ECB             :  * transformed results.
                               3062                 :  */
                               3063                 : void
 5769 tgl                      3064 GIC        1031 : transformRuleStmt(RuleStmt *stmt, const char *queryString,
                               3065                 :                   List **actions, Node **whereClause)
                               3066                 : {
                               3067                 :     Relation    rel;
                               3068                 :     ParseState *pstate;
 1193 tgl                      3069 ECB             :     ParseNamespaceItem *oldnsitem;
                               3070                 :     ParseNamespaceItem *newnsitem;
                               3071                 : 
                               3072                 :     /*
 5769                          3073                 :      * To avoid deadlock, make sure the first thing we do is grab
 3260 bruce                    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                 :      */
 1539 andres                   3078 GIC        1031 :     rel = table_openrv(stmt->relation, AccessExclusiveLock);
                               3079                 : 
 3689 kgrittn                  3080            1031 :     if (rel->rd_rel->relkind == RELKIND_MATVIEW)
 3689 kgrittn                  3081 LBC           0 :         ereport(ERROR,
 3689 kgrittn                  3082 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               3083                 :                  errmsg("rules on materialized views are not supported")));
                               3084                 : 
                               3085                 :     /* Set up pstate */
 5769 tgl                      3086 GIC        1031 :     pstate = make_parsestate(NULL);
 5769 tgl                      3087 CBC        1031 :     pstate->p_sourcetext = queryString;
                               3088                 : 
                               3089                 :     /*
 5769 tgl                      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
 1193                          3092                 :      * the rule qualification.
                               3093                 :      */
 1193 tgl                      3094 CBC        1031 :     oldnsitem = addRangeTableEntryForRelation(pstate, rel,
                               3095                 :                                               AccessShareLock,
                               3096                 :                                               makeAlias("old", NIL),
 1193 tgl                      3097 ECB             :                                               false, false);
 1193 tgl                      3098 GIC        1031 :     newnsitem = addRangeTableEntryForRelation(pstate, rel,
                               3099                 :                                               AccessShareLock,
                               3100                 :                                               makeAlias("new", NIL),
 1193 tgl                      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
 5769                          3106                 :      * rule, quals must refer to OLD.field or NEW.field to be unambiguous, but
 5769 tgl                      3107 EUB             :      * there's no need to be so picky for INSERT & DELETE.  We do not add them
                               3108                 :      * to the joinlist.
                               3109                 :      */
 5769 tgl                      3110 GIC        1031 :     switch (stmt->event)
 5769 tgl                      3111 ECB             :     {
 5769 tgl                      3112 GIC           9 :         case CMD_SELECT:
 1193                          3113               9 :             addNSItemToQuery(pstate, oldnsitem, false, true, true);
 5769 tgl                      3114 CBC           9 :             break;
 5769 tgl                      3115 GIC         719 :         case CMD_UPDATE:
 1193                          3116             719 :             addNSItemToQuery(pstate, oldnsitem, false, true, true);
 1193 tgl                      3117 CBC         719 :             addNSItemToQuery(pstate, newnsitem, false, true, true);
 5769 tgl                      3118 GIC         719 :             break;
 5769 tgl                      3119 CBC         227 :         case CMD_INSERT:
 1193 tgl                      3120 GIC         227 :             addNSItemToQuery(pstate, newnsitem, false, true, true);
 5769                          3121             227 :             break;
                               3122              76 :         case CMD_DELETE:
 1193                          3123              76 :             addNSItemToQuery(pstate, oldnsitem, false, true, true);
 5769                          3124              76 :             break;
 5769 tgl                      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 */
 5769 tgl                      3132 GIC        1031 :     *whereClause = transformWhereClause(pstate,
  660 tgl                      3133 ECB             :                                         stmt->whereClause,
                               3134                 :                                         EXPR_KIND_WHERE,
                               3135                 :                                         "WHERE");
                               3136                 :     /* we have to fix its collations too */
 4385 tgl                      3137 GIC        1031 :     assign_expr_collations(pstate, *whereClause);
                               3138                 : 
                               3139                 :     /* this is probably dead code without add_missing_from: */
 2118                          3140            1031 :     if (list_length(pstate->p_rtable) != 2) /* naughty, naughty... */
 5769 tgl                      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
 5769 tgl                      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.
 5769 tgl                      3150 EUB             :      */
 5769 tgl                      3151 GIC        1031 :     if (stmt->actions == NIL)
                               3152                 :     {
                               3153             336 :         Query      *nothing_qry = makeNode(Query);
                               3154                 : 
 5769 tgl                      3155 CBC         336 :         nothing_qry->commandType = CMD_NOTHING;
                               3156             336 :         nothing_qry->rtable = pstate->p_rtable;
  124 alvherre                 3157 GNC         336 :         nothing_qry->rteperminfos = pstate->p_rteperminfos;
 2118 tgl                      3158 GIC         336 :         nothing_qry->jointree = makeFromExpr(NIL, NULL); /* no join wanted */
                               3159                 : 
 5769                          3160             336 :         *actions = list_make1(nothing_qry);
                               3161                 :     }
                               3162                 :     else
                               3163                 :     {
 5769 tgl                      3164 ECB             :         ListCell   *l;
 5769 tgl                      3165 GIC         695 :         List       *newactions = NIL;
                               3166                 : 
                               3167                 :         /*
 5769 tgl                      3168 ECB             :          * transform each statement, like parse_sub_analyze()
                               3169                 :          */
 5769 tgl                      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                 :             /*
 5624 bruce                    3180 ECB             :              * Since outer ParseState isn't parent of inner, have to pass down
                               3181                 :              * the query text by hand.
 5769 tgl                      3182                 :              */
 5769 tgl                      3183 CBC         718 :             sub_pstate->p_sourcetext = queryString;
 5769 tgl                      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                 :              */
 1193 tgl                      3192 CBC         718 :             oldnsitem = addRangeTableEntryForRelation(sub_pstate, rel,
 1193 tgl                      3193 ECB             :                                                       AccessShareLock,
                               3194                 :                                                       makeAlias("old", NIL),
 1193 tgl                      3195 EUB             :                                                       false, false);
 1193 tgl                      3196 GBC         718 :             newnsitem = addRangeTableEntryForRelation(sub_pstate, rel,
                               3197                 :                                                       AccessShareLock,
                               3198                 :                                                       makeAlias("new", NIL),
                               3199                 :                                                       false, false);
 1193 tgl                      3200 CBC         718 :             addNSItemToQuery(sub_pstate, oldnsitem, false, true, false);
 1193 tgl                      3201 GIC         718 :             addNSItemToQuery(sub_pstate, newnsitem, false, true, false);
                               3202                 : 
                               3203                 :             /* Transform the rule action statement */
  660                          3204             718 :             top_subqry = transformStmt(sub_pstate, action);
 5769 tgl                      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
 5769 tgl                      3209 EUB             :              * the utility action execute conditionally.
                               3210                 :              */
 5769 tgl                      3211 GIC         712 :             if (top_subqry->commandType == CMD_UTILITY &&
                               3212              16 :                 *whereClause != NULL)
 5769 tgl                      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
 5769 tgl                      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                 :              */
 5769 tgl                      3222 GIC         712 :             sub_qry = getInsertSelectQuery(top_subqry, NULL);
 5769 tgl                      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                 :              */
 5769 tgl                      3230 GIC         712 :             if (sub_qry->setOperations != NULL && *whereClause != NULL)
 5769 tgl                      3231 UIC           0 :                 ereport(ERROR,
                               3232                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 5769 tgl                      3233 ECB             :                          errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
                               3234                 : 
                               3235                 :             /*
                               3236                 :              * Validate action's use of OLD/NEW, qual too
                               3237                 :              */
 5769 tgl                      3238 CBC         712 :             has_old =
 5769 tgl                      3239 GIC         987 :                 rangeTableEntry_used((Node *) sub_qry, PRS2_OLD_VARNO, 0) ||
 5769 tgl                      3240 CBC         275 :                 rangeTableEntry_used(*whereClause, PRS2_OLD_VARNO, 0);
                               3241             712 :             has_new =
 5769 tgl                      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)
 5769 tgl                      3249 UIC           0 :                         ereport(ERROR,
                               3250                 :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 5769 tgl                      3251 ECB             :                                  errmsg("ON SELECT rule cannot use OLD")));
 5769 tgl                      3252 GIC           9 :                     if (has_new)
 5769 tgl                      3253 UIC           0 :                         ereport(ERROR,
                               3254                 :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                               3255                 :                                  errmsg("ON SELECT rule cannot use NEW")));
 5769 tgl                      3256 GIC           9 :                     break;
                               3257             420 :                 case CMD_UPDATE:
                               3258                 :                     /* both are OK */
                               3259             420 :                     break;
 5769 tgl                      3260 CBC         205 :                 case CMD_INSERT:
 5769 tgl                      3261 GIC         205 :                     if (has_old)
 5769 tgl                      3262 UIC           0 :                         ereport(ERROR,
                               3263                 :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 5769 tgl                      3264 ECB             :                                  errmsg("ON INSERT rule cannot use OLD")));
 5769 tgl                      3265 GIC         205 :                     break;
                               3266              78 :                 case CMD_DELETE:
                               3267              78 :                     if (has_new)
 5769 tgl                      3268 LBC           0 :                         ereport(ERROR,
 5769 tgl                      3269 ECB             :                                 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                               3270                 :                                  errmsg("ON DELETE rule cannot use NEW")));
 5769 tgl                      3271 GIC          78 :                     break;
 5769 tgl                      3272 LBC           0 :                 default:
 5769 tgl                      3273 UIC           0 :                     elog(ERROR, "unrecognized event type: %d",
                               3274                 :                          (int) stmt->event);
                               3275                 :                     break;
                               3276                 :             }
                               3277                 : 
                               3278                 :             /*
 4559 tgl                      3279 ECB             :              * OLD/NEW are not allowed in WITH queries, because they would
                               3280                 :              * amount to outer references for the WITH, which we disallow.
 4559 tgl                      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
 4559 tgl                      3290 ECB             :              * indirect-correlated outer reference.
                               3291                 :              */
 4559 tgl                      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),
 4559 tgl                      3298 ECB             :                          errmsg("cannot refer to OLD within WITH query")));
 4559 tgl                      3299 GBC         709 :             if (rangeTableEntry_used((Node *) top_subqry->cteList,
 4559 tgl                      3300 GIC         709 :                                      PRS2_NEW_VARNO, 0) ||
                               3301             709 :                 rangeTableEntry_used((Node *) sub_qry->cteList,
                               3302                 :                                      PRS2_NEW_VARNO, 0))
 4559 tgl                      3303 UIC           0 :                 ereport(ERROR,
                               3304                 :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               3305                 :                          errmsg("cannot refer to NEW within WITH query")));
 4559 tgl                      3306 ECB             : 
 5769                          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
 5769 tgl                      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
 5769 tgl                      3320 ECB             :              * a jointree entry if only NEW and not OLD is mentioned.
 5769 tgl                      3321 EUB             :              */
 5769 tgl                      3322 GIC         709 :             if (has_old || (has_new && stmt->event == CMD_UPDATE))
                               3323                 :             {
 1193 tgl                      3324 ECB             :                 RangeTblRef *rtr;
                               3325                 : 
                               3326                 :                 /*
 5769                          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.)
 5769 tgl                      3330 EUB             :                  */
 5769 tgl                      3331 GIC         458 :                 if (sub_qry->setOperations != NULL)
 5769 tgl                      3332 UIC           0 :                     ereport(ERROR,
 5769 tgl                      3333 ECB             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               3334                 :                              errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
 1193                          3335                 :                 /* hackishly add OLD to the already-built FROM clause */
 1193 tgl                      3336 GBC         458 :                 rtr = makeNode(RangeTblRef);
 1193 tgl                      3337 GIC         458 :                 rtr->rtindex = oldnsitem->p_rtindex;
                               3338             458 :                 sub_qry->jointree->fromlist =
 1193 tgl                      3339 CBC         458 :                     lappend(sub_qry->jointree->fromlist, rtr);
 5769 tgl                      3340 EUB             :             }
                               3341                 : 
 5769 tgl                      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 */
 1539 andres                   3353            1022 :     table_close(rel, NoLock);
 5769 tgl                      3354            1022 : }
                               3355                 : 
                               3356                 : 
                               3357                 : /*
                               3358                 :  * transformAlterTableStmt -
                               3359                 :  *      parse analysis for ALTER TABLE
 5769 tgl                      3360 ECB             :  *
 1180                          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.
 3338 rhaas                    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.
 5769 tgl                      3368                 :  */
 1180                          3369                 : AlterTableStmt *
 3338 rhaas                    3370 GIC       38378 : transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
 1180 tgl                      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;
 5769 tgl                      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 */
 3338 rhaas                    3387           38378 :     rel = relation_open(relid, NoLock);
 1629 peter_e                  3388           38378 :     tupdesc = RelationGetDescr(rel);
                               3389                 : 
 2928 alvherre                 3390 ECB             :     /* Set up pstate */
 5769 tgl                      3391 GIC       38378 :     pstate = make_parsestate(NULL);
                               3392           38378 :     pstate->p_sourcetext = queryString;
 1193                          3393           38378 :     nsitem = addRangeTableEntryForRelation(pstate,
                               3394                 :                                            rel,
                               3395                 :                                            AccessShareLock,
                               3396                 :                                            NULL,
                               3397                 :                                            false,
                               3398                 :                                            true);
 1193 tgl                      3399 CBC       38378 :     addNSItemToQuery(pstate, nsitem, false, true, true);
 5769 tgl                      3400 EUB             : 
                               3401                 :     /* Set up CreateStmtContext */
 4457 tgl                      3402 GIC       38378 :     cxt.pstate = pstate;
 1180                          3403           38378 :     if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
 3680 tgl                      3404 ECB             :     {
 3680 tgl                      3405 CBC          81 :         cxt.stmtType = "ALTER FOREIGN TABLE";
                               3406              81 :         cxt.isforeign = true;
 3680 tgl                      3407 ECB             :     }
                               3408                 :     else
                               3409                 :     {
 3680 tgl                      3410 CBC       38297 :         cxt.stmtType = "ALTER TABLE";
 3680 tgl                      3411 GIC       38297 :         cxt.isforeign = false;
 3680 tgl                      3412 ECB             :     }
 5769 tgl                      3413 GIC       38378 :     cxt.relation = stmt->relation;
                               3414           38378 :     cxt.rel = rel;
 5769 tgl                      3415 CBC       38378 :     cxt.inhRelations = NIL;
 5769 tgl                      3416 GIC       38378 :     cxt.isalter = true;
                               3417           38378 :     cxt.columns = NIL;
 5769 tgl                      3418 CBC       38378 :     cxt.ckconstraints = NIL;
    2 alvherre                 3419 GNC       38378 :     cxt.nnconstraints = NIL;
 5769 tgl                      3420 GIC       38378 :     cxt.fkconstraints = NIL;
                               3421           38378 :     cxt.ixconstraints = NIL;
  871 tgl                      3422 CBC       38378 :     cxt.likeclauses = NIL;
 1861 alvherre                 3423           38378 :     cxt.extstats = NIL;
 5769 tgl                      3424 GIC       38378 :     cxt.blist = NIL;
                               3425           38378 :     cxt.alist = NIL;
                               3426           38378 :     cxt.pkey = NULL;
 2314 rhaas                    3427           38378 :     cxt.ispartitioned = (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
                               3428           38378 :     cxt.partbound = NULL;
 1948 peter_e                  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                 :      */
 5769 tgl                      3435           76729 :     foreach(lcmd, stmt->cmds)
                               3436                 :     {
                               3437           38378 :         AlterTableCmd *cmd = (AlterTableCmd *) lfirst(lcmd);
                               3438                 : 
 5769 tgl                      3439 CBC       38378 :         switch (cmd->subtype)
                               3440                 :         {
 5769 tgl                      3441 GIC         854 :             case AT_AddColumn:
                               3442                 :                 {
 2238 peter_e                  3443             854 :                     ColumnDef  *def = castNode(ColumnDef, cmd->def);
                               3444                 : 
 4457 tgl                      3445             854 :                     transformColumnDefinition(&cxt, def);
                               3446                 : 
                               3447                 :                     /*
                               3448                 :                      * If the column has a non-null default, we can't skip
 5769 tgl                      3449 ECB             :                      * validation of foreign keys.
                               3450                 :                      */
 5463 tgl                      3451 GIC         854 :                     if (def->raw_default != NULL)
 5769                          3452             318 :                         skipValidation = false;
                               3453                 : 
                               3454                 :                     /*
 5769 tgl                      3455 ECB             :                      * All constraints are processed in other ways. Remove the
                               3456                 :                      * original list
                               3457                 :                      */
 5769 tgl                      3458 GIC         854 :                     def->constraints = NIL;
 5769 tgl                      3459 ECB             : 
 5463 tgl                      3460 CBC         854 :                     newcmds = lappend(newcmds, cmd);
 5769                          3461             854 :                     break;
                               3462                 :                 }
                               3463                 : 
 5769 tgl                      3464 GIC       35411 :             case AT_AddConstraint:
                               3465                 : 
 5769 tgl                      3466 ECB             :                 /*
                               3467                 :                  * The original AddConstraint cmd node doesn't go to newcmds
                               3468                 :                  */
 5769 tgl                      3469 CBC       35411 :                 if (IsA(cmd->def, Constraint))
 5001 tgl                      3470 ECB             :                 {
 4457 tgl                      3471 GIC       35411 :                     transformTableConstraint(&cxt, (Constraint *) cmd->def);
 5001 tgl                      3472 CBC       35402 :                     if (((Constraint *) cmd->def)->contype == CONSTR_FOREIGN)
                               3473            1030 :                         skipValidation = false;
                               3474                 :                 }
                               3475                 :                 else
 5769 tgl                      3476 UIC           0 :                     elog(ERROR, "unrecognized node type: %d",
 5769 tgl                      3477 ECB             :                          (int) nodeTag(cmd->def));
 5769 tgl                      3478 CBC       35402 :                 break;
                               3479                 : 
 2928 alvherre                 3480             553 :             case AT_AlterColumnType:
 2928 alvherre                 3481 ECB             :                 {
 1180 tgl                      3482 CBC         553 :                     ColumnDef  *def = castNode(ColumnDef, cmd->def);
 2194 peter_e                  3483 ECB             :                     AttrNumber  attnum;
 2928 alvherre                 3484                 : 
                               3485                 :                     /*
                               3486                 :                      * For ALTER COLUMN TYPE, transform the USING clause if
                               3487                 :                      * one was specified.
                               3488                 :                      */
 2928 alvherre                 3489 CBC         553 :                     if (def->raw_default)
 2928 alvherre                 3490 ECB             :                     {
 2928 alvherre                 3491 CBC         108 :                         def->cooked_default =
                               3492             108 :                             transformExpr(pstate, def->raw_default,
 2928 alvherre                 3493 ECB             :                                           EXPR_KIND_ALTER_COL_TRANSFORM);
                               3494                 :                     }
                               3495                 : 
 2194 peter_e                  3496                 :                     /*
                               3497                 :                      * For identity column, create ALTER SEQUENCE command to
                               3498                 :                      * change the data type of the sequence.
                               3499                 :                      */
 2194 peter_e                  3500 GIC         553 :                     attnum = get_attnum(relid, cmd->name);
 1180 tgl                      3501             553 :                     if (attnum == InvalidAttrNumber)
 1180 tgl                      3502 LBC           0 :                         ereport(ERROR,
                               3503                 :                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
 1180 tgl                      3504 ECB             :                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
                               3505                 :                                         cmd->name, RelationGetRelationName(rel))));
 2153 bruce                    3506                 : 
  356 tgl                      3507 GIC         553 :                     if (attnum > 0 &&
  356 tgl                      3508 CBC         553 :                         TupleDescAttr(tupdesc, attnum - 1)->attidentity)
                               3509                 :                     {
 1357 peter                    3510              15 :                         Oid         seq_relid = getIdentitySequence(relid, attnum, false);
 2194 peter_e                  3511 GIC          15 :                         Oid         typeOid = typenameTypeId(pstate, def->typeName);
 2194 peter_e                  3512 CBC          15 :                         AlterSeqStmt *altseqstmt = makeNode(AlterSeqStmt);
                               3513                 : 
 2194 peter_e                  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));
 2194 peter_e                  3518 CBC          15 :                         altseqstmt->for_identity = true;
                               3519              15 :                         cxt.blist = lappend(cxt.blist, altseqstmt);
                               3520                 :                     }
                               3521                 : 
 2194 peter_e                  3522 GIC         553 :                     newcmds = lappend(newcmds, cmd);
                               3523             553 :                     break;
                               3524                 :                 }
 2194 peter_e                  3525 ECB             : 
 2194 peter_e                  3526 GIC          51 :             case AT_AddIdentity:
 2194 peter_e                  3527 ECB             :                 {
 2153 bruce                    3528 CBC          51 :                     Constraint *def = castNode(Constraint, cmd->def);
 2153 bruce                    3529 GIC          51 :                     ColumnDef  *newdef = makeNode(ColumnDef);
                               3530                 :                     AttrNumber  attnum;
 2194 peter_e                  3531 ECB             : 
 2194 peter_e                  3532 GIC          51 :                     newdef->colname = cmd->name;
                               3533              51 :                     newdef->identity = def->generated_when;
                               3534              51 :                     cmd->def = (Node *) newdef;
                               3535                 : 
 2194 peter_e                  3536 CBC          51 :                     attnum = get_attnum(relid, cmd->name);
 1180 tgl                      3537 GIC          51 :                     if (attnum == InvalidAttrNumber)
 1180 tgl                      3538 LBC           0 :                         ereport(ERROR,
 1180 tgl                      3539 ECB             :                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
                               3540                 :                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
                               3541                 :                                         cmd->name, RelationGetRelationName(rel))));
                               3542                 : 
 1180 tgl                      3543 GBC          51 :                     generateSerialExtraStmts(&cxt, newdef,
                               3544                 :                                              get_atttype(relid, attnum),
 1180 tgl                      3545 ECB             :                                              def->options, true, true,
                               3546                 :                                              NULL, NULL);
 2194 peter_e                  3547                 : 
 2194 peter_e                  3548 GIC          51 :                     newcmds = lappend(newcmds, cmd);
 2194 peter_e                  3549 CBC          51 :                     break;
                               3550                 :                 }
                               3551                 : 
 2194 peter_e                  3552 GIC          19 :             case AT_SetIdentity:
                               3553                 :                 {
                               3554                 :                     /*
                               3555                 :                      * Create an ALTER SEQUENCE statement for the internal
 2194 peter_e                  3556 ECB             :                      * sequence of the identity column.
                               3557                 :                      */
                               3558                 :                     ListCell   *lc;
 2194 peter_e                  3559 CBC          19 :                     List       *newseqopts = NIL;
 2194 peter_e                  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.
 2194 peter_e                  3567 ECB             :                      */
 2194 peter_e                  3568 CBC          50 :                     foreach(lc, castNode(List, cmd->def))
 2194 peter_e                  3569 EUB             :                     {
 2153 bruce                    3570 GIC          31 :                         DefElem    *def = lfirst_node(DefElem, lc);
                               3571                 : 
 2194 peter_e                  3572              31 :                         if (strcmp(def->defname, "generated") == 0)
                               3573              13 :                             newdef = lappend(newdef, def);
 2194 peter_e                  3574 ECB             :                         else
 2194 peter_e                  3575 CBC          18 :                             newseqopts = lappend(newseqopts, def);
                               3576                 :                     }
 2194 peter_e                  3577 ECB             : 
 2194 peter_e                  3578 CBC          19 :                     attnum = get_attnum(relid, cmd->name);
 1180 tgl                      3579              19 :                     if (attnum == InvalidAttrNumber)
 1180 tgl                      3580 UIC           0 :                         ereport(ERROR,
 1180 tgl                      3581 ECB             :                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
                               3582                 :                                  errmsg("column \"%s\" of relation \"%s\" does not exist",
                               3583                 :                                         cmd->name, RelationGetRelationName(rel))));
 2194 peter_e                  3584                 : 
 1180 tgl                      3585 CBC          19 :                     seq_relid = getIdentitySequence(relid, attnum, true);
 1357 peter                    3586 ECB             : 
 1180 tgl                      3587 GIC          19 :                     if (seq_relid)
                               3588                 :                     {
 1180 tgl                      3589 ECB             :                         AlterSeqStmt *seqstmt;
 2194 peter_e                  3590                 : 
 1180 tgl                      3591 GIC          13 :                         seqstmt = makeNode(AlterSeqStmt);
                               3592              13 :                         seqstmt->sequence = makeRangeVar(get_namespace_name(get_rel_namespace(seq_relid)),
 1180 tgl                      3593 ECB             :                                                          get_rel_name(seq_relid), -1);
 1180 tgl                      3594 GIC          13 :                         seqstmt->options = newseqopts;
 1180 tgl                      3595 CBC          13 :                         seqstmt->for_identity = true;
                               3596              13 :                         seqstmt->missing_ok = false;
                               3597                 : 
 1180 tgl                      3598 GIC          13 :                         cxt.blist = lappend(cxt.blist, seqstmt);
 2194 peter_e                  3599 ECB             :                     }
 2153 bruce                    3600                 : 
                               3601                 :                     /*
                               3602                 :                      * If column was not an identity column, we just let the
 1180 tgl                      3603                 :                      * ALTER TABLE command error out later.  (There are cases
                               3604                 :                      * this fails to cover, but we'll need to restructure
 1180 tgl                      3605 EUB             :                      * where creation of the sequence dependency linkage
                               3606                 :                      * happens before we can fix it.)
                               3607                 :                      */
                               3608                 : 
 2194 peter_e                  3609 GIC          19 :                     cmd->def = (Node *) newdef;
 2928 alvherre                 3610 CBC          19 :                     newcmds = lappend(newcmds, cmd);
 2928 alvherre                 3611 GIC          19 :                     break;
                               3612                 :                 }
                               3613                 : 
 2314 rhaas                    3614            1490 :             case AT_AttachPartition:
 2243 rhaas                    3615 ECB             :             case AT_DetachPartition:
 2314                          3616                 :                 {
 2314 rhaas                    3617 GIC        1490 :                     PartitionCmd *partcmd = (PartitionCmd *) cmd->def;
                               3618                 : 
 2243 rhaas                    3619 CBC        1490 :                     transformPartitionCmd(&cxt, partcmd);
                               3620                 :                     /* assign transformed value of the partition bound */
 2314 rhaas                    3621 GIC        1472 :                     partcmd->bound = cxt.partbound;
                               3622                 :                 }
                               3623                 : 
                               3624            1472 :                 newcmds = lappend(newcmds, cmd);
                               3625            1472 :                 break;
 2314 rhaas                    3626 ECB             : 
 5769 tgl                      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                 :                  */
 5769 tgl                      3634 UIC           0 :                 newcmds = lappend(newcmds, cmd);
 5769 tgl                      3635 LBC           0 :                 break;
                               3636                 :         }
 5769 tgl                      3637 ECB             :     }
                               3638                 : 
                               3639                 :     /*
 1447                          3640                 :      * Transfer anything we already have in cxt.alist into save_alist, to keep
                               3641                 :      * it separate from the output of transformIndexConstraints.
 5769                          3642                 :      */
 5769 tgl                      3643 GIC       38351 :     save_alist = cxt.alist;
                               3644           38351 :     cxt.alist = NIL;
 5769 tgl                      3645 ECB             : 
 2671 rhaas                    3646                 :     /* Postprocess constraints */
 4457 tgl                      3647 GBC       38351 :     transformIndexConstraints(&cxt);
 4457 tgl                      3648 GIC       38345 :     transformFKConstraints(&cxt, skipValidation, true);
 2671 rhaas                    3649           38345 :     transformCheckConstraints(&cxt, false);
                               3650                 : 
                               3651                 :     /*
 5769 tgl                      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
 4457                          3654                 :      * the IndexStmt attached to an AT_AddIndex or AT_AddIndexConstraint
                               3655                 :      * subcommand has already been through transformIndexStmt.
                               3656                 :      */
 5769 tgl                      3657 GIC       91428 :     foreach(l, cxt.alist)
 5769 tgl                      3658 ECB             :     {
 1447 tgl                      3659 CBC       53083 :         Node       *istmt = (Node *) lfirst(l);
                               3660                 : 
 1447 tgl                      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                 :          */
 1447 tgl                      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                 :         }
 1447 tgl                      3676 CBC       19176 :         else if (IsA(istmt, AlterTableStmt))
 1447 tgl                      3677 ECB             :         {
 1447 tgl                      3678 CBC       19176 :             AlterTableStmt *alterstmt = (AlterTableStmt *) istmt;
                               3679                 : 
 1447 tgl                      3680 GIC       19176 :             newcmds = list_concat(newcmds, alterstmt->cmds);
 1447 tgl                      3681 ECB             :         }
                               3682                 :         else
 1447 tgl                      3683 UIC           0 :             elog(ERROR, "unexpected stmt type %d", (int) nodeTag(istmt));
 5769 tgl                      3684 ECB             :     }
 5769 tgl                      3685 GIC       38345 :     cxt.alist = NIL;
 5769 tgl                      3686 ECB             : 
                               3687                 :     /* Append any CHECK or FK constraints to the commands list */
 5769 tgl                      3688 CBC       38717 :     foreach(l, cxt.ckconstraints)
                               3689                 :     {
 5769 tgl                      3690 GIC         372 :         newcmd = makeNode(AlterTableCmd);
 5769 tgl                      3691 CBC         372 :         newcmd->subtype = AT_AddConstraint;
    2 alvherre                 3692 GNC         372 :         newcmd->def = (Node *) lfirst_node(Constraint, l);
 5769 tgl                      3693 GIC         372 :         newcmds = lappend(newcmds, newcmd);
 5769 tgl                      3694 EUB             :     }
 5769 tgl                      3695 GIC       39378 :     foreach(l, cxt.fkconstraints)
                               3696                 :     {
                               3697            1033 :         newcmd = makeNode(AlterTableCmd);
                               3698            1033 :         newcmd->subtype = AT_AddConstraint;
    2 alvherre                 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);
 5769 tgl                      3707 GIC         227 :         newcmds = lappend(newcmds, newcmd);
 5769 tgl                      3708 EUB             :     }
                               3709                 : 
                               3710                 :     /* Append extended statistics objects */
 1861 alvherre                 3711 GIC       38345 :     transformExtendedStatistics(&cxt);
                               3712                 : 
                               3713                 :     /* Close rel */
 5769 tgl                      3714           38345 :     relation_close(rel, NoLock);
                               3715                 : 
                               3716                 :     /*
 5769 tgl                      3717 ECB             :      * Output results.
                               3718                 :      */
 5769 tgl                      3719 GIC       38345 :     stmt->cmds = newcmds;
                               3720                 : 
 1180 tgl                      3721 CBC       38345 :     *beforeStmts = cxt.blist;
                               3722           38345 :     *afterStmts = list_concat(cxt.alist, save_alist);
 5769 tgl                      3723 ECB             : 
 1180 tgl                      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
 5769 tgl                      3731 ECB             :  * and detect inconsistent/misplaced constraint attributes.
                               3732                 :  *
 5002                          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
 4457 tgl                      3738 GIC       34730 : transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList)
                               3739                 : {
 5001 tgl                      3740 CBC       34730 :     Constraint *lastprimarycon = NULL;
 5769 tgl                      3741 GIC       34730 :     bool        saw_deferrability = false;
 5769 tgl                      3742 CBC       34730 :     bool        saw_initially = false;
                               3743                 :     ListCell   *clist;
 5769 tgl                      3744 ECB             : 
 5001                          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                 : 
 5769 tgl                      3752 CBC       42310 :     foreach(clist, constraintList)
                               3753                 :     {
 5001                          3754            7580 :         Constraint *con = (Constraint *) lfirst(clist);
                               3755                 : 
 5001 tgl                      3756 GIC        7580 :         if (!IsA(con, Constraint))
 5001 tgl                      3757 UBC           0 :             elog(ERROR, "unrecognized node type: %d",
                               3758                 :                  (int) nodeTag(con));
 5001 tgl                      3759 CBC        7580 :         switch (con->contype)
                               3760                 :         {
 5001 tgl                      3761 GIC          41 :             case CONSTR_ATTR_DEFERRABLE:
 5001 tgl                      3762 CBC          41 :                 if (!SUPPORTS_ATTRS(lastprimarycon))
 5001 tgl                      3763 UIC           0 :                     ereport(ERROR,
 5001 tgl                      3764 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
                               3765                 :                              errmsg("misplaced DEFERRABLE clause"),
 4457                          3766                 :                              parser_errposition(cxt->pstate, con->location)));
 5001 tgl                      3767 CBC          41 :                 if (saw_deferrability)
 5001 tgl                      3768 UIC           0 :                     ereport(ERROR,
 5001 tgl                      3769 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
                               3770                 :                              errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
 4457                          3771                 :                              parser_errposition(cxt->pstate, con->location)));
 5001 tgl                      3772 CBC          41 :                 saw_deferrability = true;
                               3773              41 :                 lastprimarycon->deferrable = true;
                               3774              41 :                 break;
                               3775                 : 
 5001 tgl                      3776 LBC           0 :             case CONSTR_ATTR_NOT_DEFERRABLE:
 5001 tgl                      3777 UIC           0 :                 if (!SUPPORTS_ATTRS(lastprimarycon))
 5001 tgl                      3778 LBC           0 :                     ereport(ERROR,
 5001 tgl                      3779 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
                               3780                 :                              errmsg("misplaced NOT DEFERRABLE clause"),
 4457                          3781                 :                              parser_errposition(cxt->pstate, con->location)));
 5001 tgl                      3782 UIC           0 :                 if (saw_deferrability)
                               3783               0 :                     ereport(ERROR,
                               3784                 :                             (errcode(ERRCODE_SYNTAX_ERROR),
 5001 tgl                      3785 ECB             :                              errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
                               3786                 :                              parser_errposition(cxt->pstate, con->location)));
 5001 tgl                      3787 UIC           0 :                 saw_deferrability = true;
 5001 tgl                      3788 LBC           0 :                 lastprimarycon->deferrable = false;
 5001 tgl                      3789 UIC           0 :                 if (saw_initially &&
                               3790               0 :                     lastprimarycon->initdeferred)
                               3791               0 :                     ereport(ERROR,
                               3792                 :                             (errcode(ERRCODE_SYNTAX_ERROR),
 5001 tgl                      3793 ECB             :                              errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
                               3794                 :                              parser_errposition(cxt->pstate, con->location)));
 5001 tgl                      3795 LBC           0 :                 break;
 5002 tgl                      3796 ECB             : 
 5001 tgl                      3797 GIC          30 :             case CONSTR_ATTR_DEFERRED:
 5001 tgl                      3798 CBC          30 :                 if (!SUPPORTS_ATTRS(lastprimarycon))
 5001 tgl                      3799 UIC           0 :                     ereport(ERROR,
                               3800                 :                             (errcode(ERRCODE_SYNTAX_ERROR),
                               3801                 :                              errmsg("misplaced INITIALLY DEFERRED clause"),
                               3802                 :                              parser_errposition(cxt->pstate, con->location)));
 5001 tgl                      3803 GIC          30 :                 if (saw_initially)
 5001 tgl                      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)));
 5001 tgl                      3808 GIC          30 :                 saw_initially = true;
                               3809              30 :                 lastprimarycon->initdeferred = true;
                               3810                 : 
                               3811                 :                 /*
 5001 tgl                      3812 ECB             :                  * If only INITIALLY DEFERRED appears, assume DEFERRABLE
                               3813                 :                  */
 5001 tgl                      3814 CBC          30 :                 if (!saw_deferrability)
                               3815               5 :                     lastprimarycon->deferrable = true;
                               3816              25 :                 else if (!lastprimarycon->deferrable)
 5001 tgl                      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)));
 5001 tgl                      3821 GIC          30 :                 break;
                               3822                 : 
                               3823               3 :             case CONSTR_ATTR_IMMEDIATE:
                               3824               3 :                 if (!SUPPORTS_ATTRS(lastprimarycon))
 5001 tgl                      3825 UIC           0 :                     ereport(ERROR,
 5001 tgl                      3826 ECB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
                               3827                 :                              errmsg("misplaced INITIALLY IMMEDIATE clause"),
 4457                          3828                 :                              parser_errposition(cxt->pstate, con->location)));
 5001 tgl                      3829 GIC           3 :                 if (saw_initially)
 5001 tgl                      3830 LBC           0 :                     ereport(ERROR,
 5001 tgl                      3831 EUB             :                             (errcode(ERRCODE_SYNTAX_ERROR),
                               3832                 :                              errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
 4457 tgl                      3833 ECB             :                              parser_errposition(cxt->pstate, con->location)));
 5001 tgl                      3834 GIC           3 :                 saw_initially = true;
 5001 tgl                      3835 CBC           3 :                 lastprimarycon->initdeferred = false;
                               3836               3 :                 break;
 5002 tgl                      3837 EUB             : 
 5001 tgl                      3838 GIC        7506 :             default:
                               3839                 :                 /* Otherwise it's not an attribute */
                               3840            7506 :                 lastprimarycon = con;
 5001 tgl                      3841 ECB             :                 /* reset flags for new primary node */
 5001 tgl                      3842 GBC        7506 :                 saw_deferrability = false;
 5001 tgl                      3843 GIC        7506 :                 saw_initially = false;
                               3844            7506 :                 break;
                               3845                 :         }
 5769 tgl                      3846 ECB             :     }
 5769 tgl                      3847 CBC       34730 : }
 5769 tgl                      3848 ECB             : 
                               3849                 : /*
 5769 tgl                      3850 EUB             :  * Special handling of type definition for a column
                               3851                 :  */
                               3852                 : static void
 4457 tgl                      3853 GIC       34615 : transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
                               3854                 : {
                               3855                 :     /*
 4414 tgl                      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                 :      */
 4414 tgl                      3859 GIC       34615 :     Type        ctype = typenameType(cxt->pstate, column->typeName, NULL);
                               3860                 : 
 4414 tgl                      3861 GBC       34608 :     if (column->collClause)
 4414 tgl                      3862 EUB             :     {
 4414 tgl                      3863 GBC         236 :         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(ctype);
 4414 tgl                      3864 EUB             : 
 4381 peter_e                  3865 GBC         236 :         LookupCollation(cxt->pstate,
 4322 bruce                    3866 GIC         236 :                         column->collClause->collname,
                               3867             236 :                         column->collClause->location);
                               3868                 :         /* Complain if COLLATE is applied to an uncollatable type */
 4414 tgl                      3869 GBC         224 :         if (!OidIsValid(typtup->typcollation))
 4414 tgl                      3870 GIC           9 :             ereport(ERROR,
 4414 tgl                      3871 ECB             :                     (errcode(ERRCODE_DATATYPE_MISMATCH),
                               3872                 :                      errmsg("collations are not supported by type %s",
 1601 andres                   3873 EUB             :                             format_type_be(typtup->oid)),
                               3874                 :                      parser_errposition(cxt->pstate,
                               3875                 :                                         column->collClause->location)));
                               3876                 :     }
 5769 tgl                      3877 ECB             : 
 5769 tgl                      3878 GBC       34587 :     ReleaseSysCache(ctype);
 5769 tgl                      3879 GIC       34587 : }
                               3880                 : 
                               3881                 : 
 5769 tgl                      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.
 5769 tgl                      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.
 5769 tgl                      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.
 5769 tgl                      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
 5769 tgl                      3903 ECB             :  * extent.
 5769 tgl                      3904 EUB             :  */
                               3905                 : List *
 5769 tgl                      3906 GIC         649 : transformCreateSchemaStmt(CreateSchemaStmt *stmt)
                               3907                 : {
 5769 tgl                      3908 ECB             :     CreateSchemaStmtContext cxt;
                               3909                 :     List       *result;
                               3910                 :     ListCell   *elements;
                               3911                 : 
 5769 tgl                      3912 CBC         649 :     cxt.stmtType = "CREATE SCHEMA";
 5769 tgl                      3913 GIC         649 :     cxt.schemaname = stmt->schemaname;
 2953 alvherre                 3914 CBC         649 :     cxt.authrole = (RoleSpec *) stmt->authrole;
 5769 tgl                      3915 GIC         649 :     cxt.sequences = NIL;
 5769 tgl                      3916 CBC         649 :     cxt.tables = NIL;
                               3917             649 :     cxt.views = NIL;
                               3918             649 :     cxt.indexes = NIL;
 5769 tgl                      3919 GIC         649 :     cxt.triggers = NIL;
                               3920             649 :     cxt.grants = NIL;
 5769 tgl                      3921 ECB             : 
                               3922                 :     /*
                               3923                 :      * Run through each schema element in the schema element list. Separate
                               3924                 :      * statements by type, and do preliminary analysis.
                               3925                 :      */
 5769 tgl                      3926 GIC         824 :     foreach(elements, stmt->schemaElts)
 5769 tgl                      3927 ECB             :     {
 5769 tgl                      3928 GIC         175 :         Node       *element = lfirst(elements);
                               3929                 : 
                               3930             175 :         switch (nodeTag(element))
                               3931                 :         {
 5769 tgl                      3932 UIC           0 :             case T_CreateSeqStmt:
 5769 tgl                      3933 ECB             :                 {
 5769 tgl                      3934 UIC           0 :                     CreateSeqStmt *elp = (CreateSeqStmt *) element;
 5769 tgl                      3935 ECB             : 
 5769 tgl                      3936 UIC           0 :                     setSchemaName(cxt.schemaname, &elp->sequence->schemaname);
 5769 tgl                      3937 LBC           0 :                     cxt.sequences = lappend(cxt.sequences, element);
                               3938                 :                 }
                               3939               0 :                 break;
 5769 tgl                      3940 ECB             : 
 5769 tgl                      3941 CBC         161 :             case T_CreateStmt:
                               3942                 :                 {
                               3943             161 :                     CreateStmt *elp = (CreateStmt *) element;
 5769 tgl                      3944 ECB             : 
 5769 tgl                      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                 :                 }
 5769 tgl                      3952 CBC         161 :                 break;
 5769 tgl                      3953 ECB             : 
 5769 tgl                      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                 : 
 5769 tgl                      3976 UIC           0 :             case T_CreateTrigStmt:
                               3977                 :                 {
                               3978               0 :                     CreateTrigStmt *elp = (CreateTrigStmt *) element;
                               3979                 : 
 5769 tgl                      3980 LBC           0 :                     setSchemaName(cxt.schemaname, &elp->relation->schemaname);
 5769 tgl                      3981 UIC           0 :                     cxt.triggers = lappend(cxt.triggers, element);
                               3982                 :                 }
                               3983               0 :                 break;
                               3984                 : 
                               3985               0 :             case T_GrantStmt:
 5769 tgl                      3986 LBC           0 :                 cxt.grants = lappend(cxt.grants, element);
                               3987               0 :                 break;
 5769 tgl                      3988 ECB             : 
 5769 tgl                      3989 LBC           0 :             default:
                               3990               0 :                 elog(ERROR, "unrecognized node type: %d",
 5769 tgl                      3991 ECB             :                      (int) nodeTag(element));
                               3992                 :         }
                               3993                 :     }
                               3994                 : 
 5769 tgl                      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);
 5769 tgl                      4000 CBC         649 :     result = list_concat(result, cxt.triggers);
 5769 tgl                      4001 GIC         649 :     result = list_concat(result, cxt.grants);
 5769 tgl                      4002 ECB             : 
 5769 tgl                      4003 GIC         649 :     return result;
 5769 tgl                      4004 ECB             : }
                               4005                 : 
 5769 tgl                      4006 EUB             : /*
                               4007                 :  * setSchemaName
                               4008                 :  *      Set or check schema name in an element of a CREATE SCHEMA command
                               4009                 :  */
                               4010                 : static void
 5769 tgl                      4011 GBC         175 : setSchemaName(char *context_schema, char **stmt_schema_name)
                               4012                 : {
                               4013             175 :     if (*stmt_schema_name == NULL)
 5769 tgl                      4014 GIC         175 :         *stmt_schema_name = context_schema;
 5769 tgl                      4015 LBC           0 :     else if (strcmp(context_schema, *stmt_schema_name) != 0)
 5769 tgl                      4016 UIC           0 :         ereport(ERROR,
 5769 tgl                      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)));
 5769 tgl                      4021 GIC         175 : }
                               4022                 : 
                               4023                 : /*
 2243 rhaas                    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                 :  */
 2314                          4030                 : static void
 2243 rhaas                    4031 GIC        1490 : transformPartitionCmd(CreateStmtContext *cxt, PartitionCmd *cmd)
 2314 rhaas                    4032 ECB             : {
 2314 rhaas                    4033 GIC        1490 :     Relation    parentRel = cxt->rel;
                               4034                 : 
 1906 alvherre                 4035            1490 :     switch (parentRel->rd_rel->relkind)
                               4036                 :     {
 1906 alvherre                 4037 CBC        1295 :         case RELKIND_PARTITIONED_TABLE:
                               4038                 :             /* transform the partition bound, if any */
                               4039            1295 :             Assert(RelationGetPartitionKey(parentRel) != NULL);
 1906 alvherre                 4040 GIC        1295 :             if (cmd->bound != NULL)
 1906 alvherre                 4041 CBC        1043 :                 cxt->partbound = transformPartitionBound(cxt->pstate, parentRel,
                               4042                 :                                                          cmd->bound);
                               4043            1286 :             break;
 1906 alvherre                 4044 GIC         189 :         case RELKIND_PARTITIONED_INDEX:
 1132 michael                  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                 :              */
 1132 michael                  4050 GBC         189 :             if (cmd->bound != NULL)
 1132 michael                  4051 GIC           3 :                 ereport(ERROR,
 1132 michael                  4052 EUB             :                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                               4053                 :                          errmsg("\"%s\" is not a partitioned table",
                               4054                 :                                 RelationGetRelationName(parentRel))));
 1906 alvherre                 4055 GBC         186 :             break;
 1906 alvherre                 4056 GIC           6 :         case RELKIND_RELATION:
 1906 alvherre                 4057 EUB             :             /* the table must be partitioned */
 1906 alvherre                 4058 GIC           6 :             ereport(ERROR,
 1906 alvherre                 4059 EUB             :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                               4060                 :                      errmsg("table \"%s\" is not partitioned",
                               4061                 :                             RelationGetRelationName(parentRel))));
                               4062                 :             break;
 1906 alvherre                 4063 UBC           0 :         case RELKIND_INDEX:
 1906 alvherre                 4064 EUB             :             /* the index must be partitioned */
 1906 alvherre                 4065 UIC           0 :             ereport(ERROR,
                               4066                 :                     (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                               4067                 :                      errmsg("index \"%s\" is not partitioned",
                               4068                 :                             RelationGetRelationName(parentRel))));
 1906 alvherre                 4069 ECB             :             break;
 1906 alvherre                 4070 LBC           0 :         default:
 1906 alvherre                 4071 ECB             :             /* parser shouldn't let this case through */
 1906 alvherre                 4072 LBC           0 :             elog(ERROR, "\"%s\" is not a partitioned table or index",
 1906 alvherre                 4073 ECB             :                  RelationGetRelationName(parentRel));
                               4074                 :             break;
                               4075                 :     }
 2314 rhaas                    4076 GIC        1472 : }
 2314 rhaas                    4077 ECB             : 
                               4078                 : /*
                               4079                 :  * transformPartitionBound
                               4080                 :  *
                               4081                 :  * Transform a partition bound specification
                               4082                 :  */
                               4083                 : PartitionBoundSpec *
 2142 tgl                      4084 GIC        4618 : transformPartitionBound(ParseState *pstate, Relation parent,
 2142 tgl                      4085 ECB             :                         PartitionBoundSpec *spec)
                               4086                 : {
                               4087                 :     PartitionBoundSpec *result_spec;
 2314 rhaas                    4088 CBC        4618 :     PartitionKey key = RelationGetPartitionKey(parent);
 2314 rhaas                    4089 GBC        4618 :     char        strategy = get_partition_strategy(key);
                               4090            4618 :     int         partnatts = get_partition_natts(key);
 2314 rhaas                    4091 GIC        4618 :     List       *partexprs = get_partition_exprs(key);
                               4092                 : 
                               4093                 :     /* Avoid scribbling on input */
                               4094            4618 :     result_spec = copyObject(spec);
 2314 rhaas                    4095 ECB             : 
 2039 rhaas                    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                 :          */
 1977                          4104             275 :         if (strategy == PARTITION_STRATEGY_HASH)
 1977 rhaas                    4105 CBC           3 :             ereport(ERROR,
                               4106                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
 1977 rhaas                    4107 ECB             :                      errmsg("a hash-partitioned table may not have a default partition")));
                               4108                 : 
 2039                          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                 :          */
 2039 rhaas                    4114 CBC         272 :         result_spec->strategy = strategy;
 2039 rhaas                    4115 ECB             : 
 2039 rhaas                    4116 GIC         272 :         return result_spec;
 2039 rhaas                    4117 ECB             :     }
                               4118                 : 
 1977 rhaas                    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),
 1977 rhaas                    4124 ECB             :                      errmsg("invalid bound specification for a hash partition"),
                               4125                 :                      parser_errposition(pstate, exprLocation((Node *) spec))));
                               4126                 : 
 1977 rhaas                    4127 GIC         284 :         if (spec->modulus <= 0)
                               4128               6 :             ereport(ERROR,
 1977 rhaas                    4129 ECB             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
  592 fujii                    4130                 :                      errmsg("modulus for hash partition must be an integer value greater than zero")));
                               4131                 : 
 1977 rhaas                    4132 CBC         278 :         Assert(spec->remainder >= 0);
                               4133                 : 
 1977 rhaas                    4134 GIC         278 :         if (spec->remainder >= spec->modulus)
                               4135               6 :             ereport(ERROR,
                               4136                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
 1977 rhaas                    4137 EUB             :                      errmsg("remainder for hash partition must be less than modulus")));
                               4138                 :     }
 1977 rhaas                    4139 GBC        4053 :     else if (strategy == PARTITION_STRATEGY_LIST)
                               4140                 :     {
                               4141                 :         ListCell   *cell;
                               4142                 :         char       *colname;
                               4143                 :         Oid         coltype;
 2142 tgl                      4144 EUB             :         int32       coltypmod;
                               4145                 :         Oid         partcollation;
                               4146                 : 
 2142 tgl                      4147 GIC        2171 :         if (spec->strategy != PARTITION_STRATEGY_LIST)
                               4148               9 :             ereport(ERROR,
                               4149                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
 2118 tgl                      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 */
 2314 rhaas                    4154 GIC        2162 :         if (key->partattrs[0] != 0)
 1882 alvherre                 4155            2111 :             colname = get_attname(RelationGetRelid(parent),
                               4156            2111 :                                   key->partattrs[0], false);
                               4157                 :         else
 2314 rhaas                    4158 CBC          51 :             colname = deparse_expression((Node *) linitial(partexprs),
 2118 tgl                      4159 GIC          51 :                                          deparse_context_for(RelationGetRelationName(parent),
                               4160                 :                                                              RelationGetRelid(parent)),
                               4161                 :                                          false, false);
 2142 tgl                      4162 ECB             :         /* Need its type data too */
 2142 tgl                      4163 CBC        2162 :         coltype = get_partition_col_typid(key, 0);
                               4164            2162 :         coltypmod = get_partition_col_typmod(key, 0);
 1535 peter                    4165            2162 :         partcollation = get_partition_col_collation(key, 0);
                               4166                 : 
 2314 rhaas                    4167 GIC        2162 :         result_spec->listdatums = NIL;
 2314 rhaas                    4168 CBC        5175 :         foreach(cell, spec->listdatums)
                               4169                 :         {
 1535 peter                    4170            3043 :             Node       *expr = lfirst(cell);
                               4171                 :             Const      *value;
                               4172                 :             ListCell   *cell2;
                               4173                 :             bool        duplicate;
                               4174                 : 
 1535 peter                    4175 GIC        3043 :             value = transformPartitionBoundValue(pstate, expr,
                               4176                 :                                                  colname, coltype, coltypmod,
                               4177                 :                                                  partcollation);
 2314 rhaas                    4178 ECB             : 
                               4179                 :             /* Don't add to the result if the value is a duplicate */
 2314 rhaas                    4180 GIC        3013 :             duplicate = false;
                               4181            4482 :             foreach(cell2, result_spec->listdatums)
                               4182                 :             {
  629 peter                    4183            1469 :                 Const      *value2 = lfirst_node(Const, cell2);
                               4184                 : 
 2314 rhaas                    4185            1469 :                 if (equal(value, value2))
                               4186                 :                 {
 2314 rhaas                    4187 UIC           0 :                     duplicate = true;
 2314 rhaas                    4188 LBC           0 :                     break;
                               4189                 :                 }
 2314 rhaas                    4190 ECB             :             }
 2314 rhaas                    4191 GIC        3013 :             if (duplicate)
 2314 rhaas                    4192 UIC           0 :                 continue;
 2314 rhaas                    4193 ECB             : 
 2314 rhaas                    4194 GIC        3013 :             result_spec->listdatums = lappend(result_spec->listdatums,
 2314 rhaas                    4195 ECB             :                                               value);
                               4196                 :         }
                               4197                 :     }
 2314 rhaas                    4198 GIC        1882 :     else if (strategy == PARTITION_STRATEGY_RANGE)
                               4199                 :     {
                               4200            1882 :         if (spec->strategy != PARTITION_STRATEGY_RANGE)
 2314 rhaas                    4201 CBC           9 :             ereport(ERROR,
 2314 rhaas                    4202 ECB             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                               4203                 :                      errmsg("invalid bound specification for a range partition"),
                               4204                 :                      parser_errposition(pstate, exprLocation((Node *) spec))));
                               4205                 : 
 2314 rhaas                    4206 CBC        1873 :         if (list_length(spec->lowerdatums) != partnatts)
 2314 rhaas                    4207 GIC           3 :             ereport(ERROR,
 2314 rhaas                    4208 ECB             :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                               4209                 :                      errmsg("FROM must specify exactly one value per partitioning column")));
 2314 rhaas                    4210 GIC        1870 :         if (list_length(spec->upperdatums) != partnatts)
                               4211               3 :             ereport(ERROR,
                               4212                 :                     (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
 2314 rhaas                    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                 :          */
 1535 peter                    4219 GIC        1834 :         result_spec->lowerdatums =
 1418 tgl                      4220            1867 :             transformPartitionRangeBounds(pstate, spec->lowerdatums,
 1418 tgl                      4221 ECB             :                                           parent);
 1535 peter                    4222 CBC        1831 :         result_spec->upperdatums =
 1418 tgl                      4223 GIC        1834 :             transformPartitionRangeBounds(pstate, spec->upperdatums,
                               4224                 :                                           parent);
                               4225                 :     }
                               4226                 :     else
 1535 peter                    4227 UIC           0 :         elog(ERROR, "unexpected partition strategy: %d", (int) strategy);
 1535 peter                    4228 ECB             : 
 1535 peter                    4229 CBC        4235 :     return result_spec;
 1535 peter                    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 *
 1535 peter                    4238 CBC        3701 : transformPartitionRangeBounds(ParseState *pstate, List *blist,
 1535 peter                    4239 ECB             :                               Relation parent)
                               4240                 : {
 1535 peter                    4241 CBC        3701 :     List       *result = NIL;
                               4242            3701 :     PartitionKey key = RelationGetPartitionKey(parent);
 1535 peter                    4243 GIC        3701 :     List       *partexprs = get_partition_exprs(key);
 1535 peter                    4244 ECB             :     ListCell   *lc;
                               4245                 :     int         i,
                               4246                 :                 j;
                               4247                 : 
 1535 peter                    4248 GIC        3701 :     i = j = 0;
 1535 peter                    4249 CBC        8333 :     foreach(lc, blist)
                               4250                 :     {
 1418 tgl                      4251 GIC        4659 :         Node       *expr = lfirst(lc);
 1535 peter                    4252            4659 :         PartitionRangeDatum *prd = NULL;
                               4253                 : 
 1535 peter                    4254 ECB             :         /*
 1418 tgl                      4255                 :          * Infinite range bounds -- "minvalue" and "maxvalue" -- get passed in
                               4256                 :          * as ColumnRefs.
 2032 rhaas                    4257                 :          */
 1535 peter                    4258 GIC        4659 :         if (IsA(expr, ColumnRef))
 1535 peter                    4259 ECB             :         {
 1418 tgl                      4260 GIC         369 :             ColumnRef  *cref = (ColumnRef *) expr;
 1418 tgl                      4261 GBC         369 :             char       *cname = NULL;
 1535 peter                    4262 EUB             : 
                               4263                 :             /*
                               4264                 :              * There should be a single field named either "minvalue" or
 1475 michael                  4265 ECB             :              * "maxvalue".
 1475 michael                  4266 EUB             :              */
 1535 peter                    4267 GIC         369 :             if (list_length(cref->fields) == 1 &&
 1535 peter                    4268 CBC         366 :                 IsA(linitial(cref->fields), String))
 1535 peter                    4269 GIC         366 :                 cname = strVal(linitial(cref->fields));
                               4270                 : 
 1475 michael                  4271             369 :             if (cname == NULL)
 1475 michael                  4272 ECB             :             {
                               4273                 :                 /*
 1418 tgl                      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                 :             }
 1475 michael                  4280 CBC         366 :             else if (strcmp("minvalue", cname) == 0)
 1535 peter                    4281 ECB             :             {
 1535 peter                    4282 GIC         186 :                 prd = makeNode(PartitionRangeDatum);
                               4283             186 :                 prd->kind = PARTITION_RANGE_DATUM_MINVALUE;
 1535 peter                    4284 CBC         186 :                 prd->value = NULL;
 1535 peter                    4285 ECB             :             }
 1535 peter                    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                 :         }
 1535 peter                    4293 ECB             : 
 1535 peter                    4294 CBC        4659 :         if (prd == NULL)
                               4295                 :         {
 2142 tgl                      4296 ECB             :             char       *colname;
                               4297                 :             Oid         coltype;
                               4298                 :             int32       coltypmod;
                               4299                 :             Oid         partcollation;
                               4300                 :             Const      *value;
 2142 tgl                      4301 EUB             : 
                               4302                 :             /* Get the column's name in case we need to output an error */
 2314 rhaas                    4303 CBC        4299 :             if (key->partattrs[i] != 0)
 1882 alvherre                 4304 GIC        3890 :                 colname = get_attname(RelationGetRelid(parent),
                               4305            3890 :                                       key->partattrs[i], false);
                               4306                 :             else
                               4307                 :             {
 2314 rhaas                    4308             409 :                 colname = deparse_expression((Node *) list_nth(partexprs, j),
 2118 tgl                      4309             409 :                                              deparse_context_for(RelationGetRelationName(parent),
                               4310                 :                                                                  RelationGetRelid(parent)),
                               4311                 :                                              false, false);
 2314 rhaas                    4312 CBC         409 :                 ++j;
                               4313                 :             }
                               4314                 : 
 2142 tgl                      4315 ECB             :             /* Need its type data too */
 2142 tgl                      4316 CBC        4299 :             coltype = get_partition_col_typid(key, i);
                               4317            4299 :             coltypmod = get_partition_col_typmod(key, i);
 1535 peter                    4318 GIC        4299 :             partcollation = get_partition_col_collation(key, i);
                               4319                 : 
                               4320            4299 :             value = transformPartitionBoundValue(pstate, expr,
                               4321                 :                                                  colname,
 1535 peter                    4322 ECB             :                                                  coltype, coltypmod,
                               4323                 :                                                  partcollation);
 1535 peter                    4324 GIC        4275 :             if (value->constisnull)
 1535 peter                    4325 CBC           3 :                 ereport(ERROR,
 1535 peter                    4326 ECB             :                         (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                               4327                 :                          errmsg("cannot specify NULL in range bound")));
 1535 peter                    4328 GIC        4272 :             prd = makeNode(PartitionRangeDatum);
                               4329            4272 :             prd->kind = PARTITION_RANGE_DATUM_VALUE;
                               4330            4272 :             prd->value = (Node *) value;
 2314 rhaas                    4331            4272 :             ++i;
 2314 rhaas                    4332 ECB             :         }
                               4333                 : 
 1535 peter                    4334 CBC        4632 :         prd->location = exprLocation(expr);
 1535 peter                    4335 ECB             : 
 1535 peter                    4336 GIC        4632 :         result = lappend(result, prd);
                               4337                 :     }
                               4338                 : 
                               4339                 :     /*
                               4340                 :      * Once we see MINVALUE or MAXVALUE for one column, the remaining columns
 1418 tgl                      4341 ECB             :      * must be the same.
 1535 peter                    4342                 :      */
 1535 peter                    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                 :  */
 2032 rhaas                    4354 ECB             : static void
 2032 rhaas                    4355 GIC        3674 : validateInfiniteBounds(ParseState *pstate, List *blist)
 2032 rhaas                    4356 ECB             : {
 1977                          4357                 :     ListCell   *lc;
 2032 rhaas                    4358 CBC        3674 :     PartitionRangeDatumKind kind = PARTITION_RANGE_DATUM_VALUE;
                               4359                 : 
                               4360            8294 :     foreach(lc, blist)
                               4361                 :     {
  629 peter                    4362            4629 :         PartitionRangeDatum *prd = lfirst_node(PartitionRangeDatum, lc);
 2032 rhaas                    4363 ECB             : 
 2032 rhaas                    4364 CBC        4629 :         if (kind == prd->kind)
 2032 rhaas                    4365 GIC        4365 :             continue;
                               4366                 : 
                               4367             264 :         switch (kind)
 2032 rhaas                    4368 ECB             :         {
 2032 rhaas                    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"),
 2032 rhaas                    4377 ECB             :                          parser_errposition(pstate, exprLocation((Node *) prd))));
 1804 tgl                      4378                 :                 break;
 2032 rhaas                    4379                 : 
 2032 rhaas                    4380 GIC           6 :             case PARTITION_RANGE_DATUM_MINVALUE:
                               4381               6 :                 ereport(ERROR,
 2032 rhaas                    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                 :     }
 2032 rhaas                    4388 GIC        3665 : }
                               4389                 : 
 2142 tgl                      4390 ECB             : /*
  928                          4391                 :  * Transform one entry in a partition bound spec, producing a constant.
 2142                          4392                 :  */
                               4393                 : static Const *
 1535 peter                    4394 CBC        7342 : transformPartitionBoundValue(ParseState *pstate, Node *val,
                               4395                 :                              const char *colName, Oid colType, int32 colTypmod,
                               4396                 :                              Oid partCollation)
                               4397                 : {
 2142 tgl                      4398 ECB             :     Node       *value;
                               4399                 : 
                               4400                 :     /* Transform raw parsetree */
 1535 peter                    4401 GIC        7342 :     value = transformExpr(pstate, val, EXPR_KIND_PARTITION_BOUND);
 1535 peter                    4402 ECB             : 
  928 tgl                      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                 :      */
  928 tgl                      4408 CBC        7291 :     Assert(!contain_var_clause(value));
                               4409                 : 
  928 tgl                      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                 :      */
 2142 tgl                      4415 GIC        7291 :     value = coerce_to_target_type(pstate,
                               4416                 :                                   value, exprType(value),
 2142 tgl                      4417 ECB             :                                   colType,
                               4418                 :                                   colTypmod,
                               4419                 :                                   COERCION_ASSIGNMENT,
                               4420                 :                                   COERCE_IMPLICIT_CAST,
                               4421                 :                                   -1);
                               4422                 : 
 2142 tgl                      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))));
 2142 tgl                      4429 ECB             : 
                               4430                 :     /*
                               4431                 :      * Evaluate the expression, if needed, assigning the partition key's data
  928                          4432                 :      * type and collation to the resulting Const node.
                               4433                 :      */
  928 tgl                      4434 CBC        7288 :     if (!IsA(value, Const))
                               4435                 :     {
  923                          4436             260 :         assign_expr_collations(pstate, value);
  928 tgl                      4437 GIC         260 :         value = (Node *) expression_planner((Expr *) value);
  928 tgl                      4438 CBC         260 :         value = (Node *) evaluate_expr((Expr *) value, colType, colTypmod,
  928 tgl                      4439 ECB             :                                        partCollation);
  928 tgl                      4440 GIC         260 :         if (!IsA(value, Const))
  928 tgl                      4441 LBC           0 :             elog(ERROR, "could not evaluate partition bound expression");
                               4442                 :     }
  928 tgl                      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                 :          */
  928 tgl                      4451 GIC        7028 :         ((Const *) value)->constcollid = partCollation;
                               4452                 :     }
                               4453                 : 
 1535 peter                    4454 ECB             :     /*
  928 tgl                      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                 :      */
  928 tgl                      4459 GIC        7288 :     ((Const *) value)->location = exprLocation(val);
                               4460                 : 
 2142                          4461            7288 :     return (Const *) value;
 2314 rhaas                    4462 ECB             : }
        

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