LCOV - code coverage report
Current view: top level - src/backend/parser - analyze.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 1042 1145 91.0 %
Date: 2025-07-04 00:16:42 Functions: 36 37 97.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * analyze.c
       4             :  *    transform the raw parse tree into a query tree
       5             :  *
       6             :  * For optimizable statements, we are careful to obtain a suitable lock on
       7             :  * each referenced table, and other modules of the backend preserve or
       8             :  * re-obtain these locks before depending on the results.  It is therefore
       9             :  * okay to do significant semantic analysis of these statements.  For
      10             :  * utility commands, no locks are obtained here (and if they were, we could
      11             :  * not be sure we'd still have them at execution).  Hence the general rule
      12             :  * for utility commands is to just dump them into a Query node untransformed.
      13             :  * DECLARE CURSOR, EXPLAIN, and CREATE TABLE AS are exceptions because they
      14             :  * contain optimizable statements, which we should transform.
      15             :  *
      16             :  *
      17             :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
      18             :  * Portions Copyright (c) 1994, Regents of the University of California
      19             :  *
      20             :  *  src/backend/parser/analyze.c
      21             :  *
      22             :  *-------------------------------------------------------------------------
      23             :  */
      24             : 
      25             : #include "postgres.h"
      26             : 
      27             : #include "access/sysattr.h"
      28             : #include "catalog/pg_proc.h"
      29             : #include "catalog/pg_type.h"
      30             : #include "commands/defrem.h"
      31             : #include "miscadmin.h"
      32             : #include "nodes/makefuncs.h"
      33             : #include "nodes/nodeFuncs.h"
      34             : #include "nodes/queryjumble.h"
      35             : #include "optimizer/optimizer.h"
      36             : #include "parser/analyze.h"
      37             : #include "parser/parse_agg.h"
      38             : #include "parser/parse_clause.h"
      39             : #include "parser/parse_coerce.h"
      40             : #include "parser/parse_collate.h"
      41             : #include "parser/parse_cte.h"
      42             : #include "parser/parse_expr.h"
      43             : #include "parser/parse_func.h"
      44             : #include "parser/parse_merge.h"
      45             : #include "parser/parse_oper.h"
      46             : #include "parser/parse_param.h"
      47             : #include "parser/parse_relation.h"
      48             : #include "parser/parse_target.h"
      49             : #include "parser/parse_type.h"
      50             : #include "parser/parsetree.h"
      51             : #include "utils/backend_status.h"
      52             : #include "utils/builtins.h"
      53             : #include "utils/guc.h"
      54             : #include "utils/rel.h"
      55             : #include "utils/syscache.h"
      56             : 
      57             : 
      58             : /* Hook for plugins to get control at end of parse analysis */
      59             : post_parse_analyze_hook_type post_parse_analyze_hook = NULL;
      60             : 
      61             : static Query *transformOptionalSelectInto(ParseState *pstate, Node *parseTree);
      62             : static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
      63             : static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
      64             : static OnConflictExpr *transformOnConflictClause(ParseState *pstate,
      65             :                                                  OnConflictClause *onConflictClause);
      66             : static int  count_rowexpr_columns(ParseState *pstate, Node *expr);
      67             : static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
      68             : static Query *transformValuesClause(ParseState *pstate, SelectStmt *stmt);
      69             : static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
      70             : static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
      71             :                                        bool isTopLevel, List **targetlist);
      72             : static void determineRecursiveColTypes(ParseState *pstate,
      73             :                                        Node *larg, List *nrtargetlist);
      74             : static Query *transformReturnStmt(ParseState *pstate, ReturnStmt *stmt);
      75             : static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
      76             : static Query *transformPLAssignStmt(ParseState *pstate,
      77             :                                     PLAssignStmt *stmt);
      78             : static Query *transformDeclareCursorStmt(ParseState *pstate,
      79             :                                          DeclareCursorStmt *stmt);
      80             : static Query *transformExplainStmt(ParseState *pstate,
      81             :                                    ExplainStmt *stmt);
      82             : static Query *transformCreateTableAsStmt(ParseState *pstate,
      83             :                                          CreateTableAsStmt *stmt);
      84             : static Query *transformCallStmt(ParseState *pstate,
      85             :                                 CallStmt *stmt);
      86             : static void transformLockingClause(ParseState *pstate, Query *qry,
      87             :                                    LockingClause *lc, bool pushedDown);
      88             : #ifdef DEBUG_NODE_TESTS_ENABLED
      89             : static bool test_raw_expression_coverage(Node *node, void *context);
      90             : #endif
      91             : 
      92             : 
      93             : /*
      94             :  * parse_analyze_fixedparams
      95             :  *      Analyze a raw parse tree and transform it to Query form.
      96             :  *
      97             :  * Optionally, information about $n parameter types can be supplied.
      98             :  * References to $n indexes not defined by paramTypes[] are disallowed.
      99             :  *
     100             :  * The result is a Query node.  Optimizable statements require considerable
     101             :  * transformation, while utility-type statements are simply hung off
     102             :  * a dummy CMD_UTILITY Query node.
     103             :  */
     104             : Query *
     105      780070 : parse_analyze_fixedparams(RawStmt *parseTree, const char *sourceText,
     106             :                           const Oid *paramTypes, int numParams,
     107             :                           QueryEnvironment *queryEnv)
     108             : {
     109      780070 :     ParseState *pstate = make_parsestate(NULL);
     110             :     Query      *query;
     111      780070 :     JumbleState *jstate = NULL;
     112             : 
     113             :     Assert(sourceText != NULL); /* required as of 8.4 */
     114             : 
     115      780070 :     pstate->p_sourcetext = sourceText;
     116             : 
     117      780070 :     if (numParams > 0)
     118        3946 :         setup_parse_fixed_parameters(pstate, paramTypes, numParams);
     119             : 
     120      780070 :     pstate->p_queryEnv = queryEnv;
     121             : 
     122      780070 :     query = transformTopLevelStmt(pstate, parseTree);
     123             : 
     124      772446 :     if (IsQueryIdEnabled())
     125      138644 :         jstate = JumbleQuery(query);
     126             : 
     127      772446 :     if (post_parse_analyze_hook)
     128      138530 :         (*post_parse_analyze_hook) (pstate, query, jstate);
     129             : 
     130      772446 :     free_parsestate(pstate);
     131             : 
     132      772446 :     pgstat_report_query_id(query->queryId, false);
     133             : 
     134      772446 :     return query;
     135             : }
     136             : 
     137             : /*
     138             :  * parse_analyze_varparams
     139             :  *
     140             :  * This variant is used when it's okay to deduce information about $n
     141             :  * symbol datatypes from context.  The passed-in paramTypes[] array can
     142             :  * be modified or enlarged (via repalloc).
     143             :  */
     144             : Query *
     145       13118 : parse_analyze_varparams(RawStmt *parseTree, const char *sourceText,
     146             :                         Oid **paramTypes, int *numParams,
     147             :                         QueryEnvironment *queryEnv)
     148             : {
     149       13118 :     ParseState *pstate = make_parsestate(NULL);
     150             :     Query      *query;
     151       13118 :     JumbleState *jstate = NULL;
     152             : 
     153             :     Assert(sourceText != NULL); /* required as of 8.4 */
     154             : 
     155       13118 :     pstate->p_sourcetext = sourceText;
     156             : 
     157       13118 :     setup_parse_variable_parameters(pstate, paramTypes, numParams);
     158             : 
     159       13118 :     pstate->p_queryEnv = queryEnv;
     160             : 
     161       13118 :     query = transformTopLevelStmt(pstate, parseTree);
     162             : 
     163             :     /* make sure all is well with parameter types */
     164       13102 :     check_variable_parameters(pstate, query);
     165             : 
     166       13102 :     if (IsQueryIdEnabled())
     167         510 :         jstate = JumbleQuery(query);
     168             : 
     169       13102 :     if (post_parse_analyze_hook)
     170         510 :         (*post_parse_analyze_hook) (pstate, query, jstate);
     171             : 
     172       13102 :     free_parsestate(pstate);
     173             : 
     174       13102 :     pgstat_report_query_id(query->queryId, false);
     175             : 
     176       13102 :     return query;
     177             : }
     178             : 
     179             : /*
     180             :  * parse_analyze_withcb
     181             :  *
     182             :  * This variant is used when the caller supplies their own parser callback to
     183             :  * resolve parameters and possibly other things.
     184             :  */
     185             : Query *
     186       37486 : parse_analyze_withcb(RawStmt *parseTree, const char *sourceText,
     187             :                      ParserSetupHook parserSetup,
     188             :                      void *parserSetupArg,
     189             :                      QueryEnvironment *queryEnv)
     190             : {
     191       37486 :     ParseState *pstate = make_parsestate(NULL);
     192             :     Query      *query;
     193       37486 :     JumbleState *jstate = NULL;
     194             : 
     195             :     Assert(sourceText != NULL); /* required as of 8.4 */
     196             : 
     197       37486 :     pstate->p_sourcetext = sourceText;
     198       37486 :     pstate->p_queryEnv = queryEnv;
     199       37486 :     (*parserSetup) (pstate, parserSetupArg);
     200             : 
     201       37486 :     query = transformTopLevelStmt(pstate, parseTree);
     202             : 
     203       37368 :     if (IsQueryIdEnabled())
     204        7404 :         jstate = JumbleQuery(query);
     205             : 
     206       37368 :     if (post_parse_analyze_hook)
     207        7384 :         (*post_parse_analyze_hook) (pstate, query, jstate);
     208             : 
     209       37368 :     free_parsestate(pstate);
     210             : 
     211       37368 :     pgstat_report_query_id(query->queryId, false);
     212             : 
     213       37368 :     return query;
     214             : }
     215             : 
     216             : 
     217             : /*
     218             :  * parse_sub_analyze
     219             :  *      Entry point for recursively analyzing a sub-statement.
     220             :  */
     221             : Query *
     222      101724 : parse_sub_analyze(Node *parseTree, ParseState *parentParseState,
     223             :                   CommonTableExpr *parentCTE,
     224             :                   bool locked_from_parent,
     225             :                   bool resolve_unknowns)
     226             : {
     227      101724 :     ParseState *pstate = make_parsestate(parentParseState);
     228             :     Query      *query;
     229             : 
     230      101724 :     pstate->p_parent_cte = parentCTE;
     231      101724 :     pstate->p_locked_from_parent = locked_from_parent;
     232      101724 :     pstate->p_resolve_unknowns = resolve_unknowns;
     233             : 
     234      101724 :     query = transformStmt(pstate, parseTree);
     235             : 
     236      101518 :     free_parsestate(pstate);
     237             : 
     238      101518 :     return query;
     239             : }
     240             : 
     241             : /*
     242             :  * transformTopLevelStmt -
     243             :  *    transform a Parse tree into a Query tree.
     244             :  *
     245             :  * This function is just responsible for transferring statement location data
     246             :  * from the RawStmt into the finished Query.
     247             :  */
     248             : Query *
     249      833644 : transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
     250             : {
     251             :     Query      *result;
     252             : 
     253             :     /* We're at top level, so allow SELECT INTO */
     254      833644 :     result = transformOptionalSelectInto(pstate, parseTree->stmt);
     255             : 
     256      825880 :     result->stmt_location = parseTree->stmt_location;
     257      825880 :     result->stmt_len = parseTree->stmt_len;
     258             : 
     259      825880 :     return result;
     260             : }
     261             : 
     262             : /*
     263             :  * transformOptionalSelectInto -
     264             :  *    If SELECT has INTO, convert it to CREATE TABLE AS.
     265             :  *
     266             :  * The only thing we do here that we don't do in transformStmt() is to
     267             :  * convert SELECT ... INTO into CREATE TABLE AS.  Since utility statements
     268             :  * aren't allowed within larger statements, this is only allowed at the top
     269             :  * of the parse tree, and so we only try it before entering the recursive
     270             :  * transformStmt() processing.
     271             :  */
     272             : static Query *
     273      857548 : transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
     274             : {
     275      857548 :     if (IsA(parseTree, SelectStmt))
     276             :     {
     277      365374 :         SelectStmt *stmt = (SelectStmt *) parseTree;
     278             : 
     279             :         /* If it's a set-operation tree, drill down to leftmost SelectStmt */
     280      375826 :         while (stmt && stmt->op != SETOP_NONE)
     281       10452 :             stmt = stmt->larg;
     282             :         Assert(stmt && IsA(stmt, SelectStmt) && stmt->larg == NULL);
     283             : 
     284      365374 :         if (stmt->intoClause)
     285             :         {
     286         102 :             CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt);
     287             : 
     288         102 :             ctas->query = parseTree;
     289         102 :             ctas->into = stmt->intoClause;
     290         102 :             ctas->objtype = OBJECT_TABLE;
     291         102 :             ctas->is_select_into = true;
     292             : 
     293             :             /*
     294             :              * Remove the intoClause from the SelectStmt.  This makes it safe
     295             :              * for transformSelectStmt to complain if it finds intoClause set
     296             :              * (implying that the INTO appeared in a disallowed place).
     297             :              */
     298         102 :             stmt->intoClause = NULL;
     299             : 
     300         102 :             parseTree = (Node *) ctas;
     301             :         }
     302             :     }
     303             : 
     304      857548 :     return transformStmt(pstate, parseTree);
     305             : }
     306             : 
     307             : /*
     308             :  * transformStmt -
     309             :  *    recursively transform a Parse tree into a Query tree.
     310             :  */
     311             : Query *
     312      979798 : transformStmt(ParseState *pstate, Node *parseTree)
     313             : {
     314             :     Query      *result;
     315             : 
     316             : #ifdef DEBUG_NODE_TESTS_ENABLED
     317             : 
     318             :     /*
     319             :      * We apply debug_raw_expression_coverage_test testing to basic DML
     320             :      * statements; we can't just run it on everything because
     321             :      * raw_expression_tree_walker() doesn't claim to handle utility
     322             :      * statements.
     323             :      */
     324      979798 :     if (Debug_raw_expression_coverage_test)
     325             :     {
     326      979798 :         switch (nodeTag(parseTree))
     327             :         {
     328      569514 :             case T_SelectStmt:
     329             :             case T_InsertStmt:
     330             :             case T_UpdateStmt:
     331             :             case T_DeleteStmt:
     332             :             case T_MergeStmt:
     333      569514 :                 (void) test_raw_expression_coverage(parseTree, NULL);
     334      569514 :                 break;
     335      410284 :             default:
     336      410284 :                 break;
     337             :         }
     338             :     }
     339             : #endif                          /* DEBUG_NODE_TESTS_ENABLED */
     340             : 
     341             :     /*
     342             :      * Caution: when changing the set of statement types that have non-default
     343             :      * processing here, see also stmt_requires_parse_analysis() and
     344             :      * analyze_requires_snapshot().
     345             :      */
     346      979798 :     switch (nodeTag(parseTree))
     347             :     {
     348             :             /*
     349             :              * Optimizable statements
     350             :              */
     351       68000 :         case T_InsertStmt:
     352       68000 :             result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
     353       66584 :             break;
     354             : 
     355        4488 :         case T_DeleteStmt:
     356        4488 :             result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
     357        4434 :             break;
     358             : 
     359       13770 :         case T_UpdateStmt:
     360       13770 :             result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
     361       13666 :             break;
     362             : 
     363        2016 :         case T_MergeStmt:
     364        2016 :             result = transformMergeStmt(pstate, (MergeStmt *) parseTree);
     365        1950 :             break;
     366             : 
     367      481240 :         case T_SelectStmt:
     368             :             {
     369      481240 :                 SelectStmt *n = (SelectStmt *) parseTree;
     370             : 
     371      481240 :                 if (n->valuesLists)
     372        8464 :                     result = transformValuesClause(pstate, n);
     373      472776 :                 else if (n->op == SETOP_NONE)
     374      460184 :                     result = transformSelectStmt(pstate, n);
     375             :                 else
     376       12592 :                     result = transformSetOperationStmt(pstate, n);
     377             :             }
     378      474950 :             break;
     379             : 
     380        4870 :         case T_ReturnStmt:
     381        4870 :             result = transformReturnStmt(pstate, (ReturnStmt *) parseTree);
     382        4864 :             break;
     383             : 
     384        5376 :         case T_PLAssignStmt:
     385        5376 :             result = transformPLAssignStmt(pstate,
     386             :                                            (PLAssignStmt *) parseTree);
     387        5350 :             break;
     388             : 
     389             :             /*
     390             :              * Special cases
     391             :              */
     392        4568 :         case T_DeclareCursorStmt:
     393        4568 :             result = transformDeclareCursorStmt(pstate,
     394             :                                                 (DeclareCursorStmt *) parseTree);
     395        4546 :             break;
     396             : 
     397       23904 :         case T_ExplainStmt:
     398       23904 :             result = transformExplainStmt(pstate,
     399             :                                           (ExplainStmt *) parseTree);
     400       23896 :             break;
     401             : 
     402        1996 :         case T_CreateTableAsStmt:
     403        1996 :             result = transformCreateTableAsStmt(pstate,
     404             :                                                 (CreateTableAsStmt *) parseTree);
     405        1992 :             break;
     406             : 
     407         522 :         case T_CallStmt:
     408         522 :             result = transformCallStmt(pstate,
     409             :                                        (CallStmt *) parseTree);
     410         490 :             break;
     411             : 
     412      369048 :         default:
     413             : 
     414             :             /*
     415             :              * other statements don't require any transformation; just return
     416             :              * the original parsetree with a Query node plastered on top.
     417             :              */
     418      369048 :             result = makeNode(Query);
     419      369048 :             result->commandType = CMD_UTILITY;
     420      369048 :             result->utilityStmt = (Node *) parseTree;
     421      369048 :             break;
     422             :     }
     423             : 
     424             :     /* Mark as original query until we learn differently */
     425      971770 :     result->querySource = QSRC_ORIGINAL;
     426      971770 :     result->canSetTag = true;
     427             : 
     428      971770 :     return result;
     429             : }
     430             : 
     431             : /*
     432             :  * stmt_requires_parse_analysis
     433             :  *      Returns true if parse analysis will do anything non-trivial
     434             :  *      with the given raw parse tree.
     435             :  *
     436             :  * Generally, this should return true for any statement type for which
     437             :  * transformStmt() does more than wrap a CMD_UTILITY Query around it.
     438             :  * When it returns false, the caller can assume that there is no situation
     439             :  * in which parse analysis of the raw statement could need to be re-done.
     440             :  *
     441             :  * Currently, since the rewriter and planner do nothing for CMD_UTILITY
     442             :  * Queries, a false result means that the entire parse analysis/rewrite/plan
     443             :  * pipeline will never need to be re-done.  If that ever changes, callers
     444             :  * will likely need adjustment.
     445             :  */
     446             : bool
     447    28278986 : stmt_requires_parse_analysis(RawStmt *parseTree)
     448             : {
     449             :     bool        result;
     450             : 
     451    28278986 :     switch (nodeTag(parseTree->stmt))
     452             :     {
     453             :             /*
     454             :              * Optimizable statements
     455             :              */
     456    27404670 :         case T_InsertStmt:
     457             :         case T_DeleteStmt:
     458             :         case T_UpdateStmt:
     459             :         case T_MergeStmt:
     460             :         case T_SelectStmt:
     461             :         case T_ReturnStmt:
     462             :         case T_PLAssignStmt:
     463    27404670 :             result = true;
     464    27404670 :             break;
     465             : 
     466             :             /*
     467             :              * Special cases
     468             :              */
     469       50460 :         case T_DeclareCursorStmt:
     470             :         case T_ExplainStmt:
     471             :         case T_CreateTableAsStmt:
     472             :         case T_CallStmt:
     473       50460 :             result = true;
     474       50460 :             break;
     475             : 
     476      823856 :         default:
     477             :             /* all other statements just get wrapped in a CMD_UTILITY Query */
     478      823856 :             result = false;
     479      823856 :             break;
     480             :     }
     481             : 
     482    28278986 :     return result;
     483             : }
     484             : 
     485             : /*
     486             :  * analyze_requires_snapshot
     487             :  *      Returns true if a snapshot must be set before doing parse analysis
     488             :  *      on the given raw parse tree.
     489             :  */
     490             : bool
     491      733098 : analyze_requires_snapshot(RawStmt *parseTree)
     492             : {
     493             :     /*
     494             :      * Currently, this should return true in exactly the same cases that
     495             :      * stmt_requires_parse_analysis() does, so we just invoke that function
     496             :      * rather than duplicating it.  We keep the two entry points separate for
     497             :      * clarity of callers, since from the callers' standpoint these are
     498             :      * different conditions.
     499             :      *
     500             :      * While there may someday be a statement type for which transformStmt()
     501             :      * does something nontrivial and yet no snapshot is needed for that
     502             :      * processing, it seems likely that making such a choice would be fragile.
     503             :      * If you want to install an exception, document the reasoning for it in a
     504             :      * comment.
     505             :      */
     506      733098 :     return stmt_requires_parse_analysis(parseTree);
     507             : }
     508             : 
     509             : /*
     510             :  * query_requires_rewrite_plan()
     511             :  *      Returns true if rewriting or planning is non-trivial for this Query.
     512             :  *
     513             :  * This is much like stmt_requires_parse_analysis(), but applies one step
     514             :  * further down the pipeline.
     515             :  *
     516             :  * We do not provide an equivalent of analyze_requires_snapshot(): callers
     517             :  * can assume that any rewriting or planning activity needs a snapshot.
     518             :  */
     519             : bool
     520      527738 : query_requires_rewrite_plan(Query *query)
     521             : {
     522             :     bool        result;
     523             : 
     524      527738 :     if (query->commandType != CMD_UTILITY)
     525             :     {
     526             :         /* All optimizable statements require rewriting/planning */
     527      527738 :         result = true;
     528             :     }
     529             :     else
     530             :     {
     531             :         /* This list should match stmt_requires_parse_analysis() */
     532           0 :         switch (nodeTag(query->utilityStmt))
     533             :         {
     534           0 :             case T_DeclareCursorStmt:
     535             :             case T_ExplainStmt:
     536             :             case T_CreateTableAsStmt:
     537             :             case T_CallStmt:
     538           0 :                 result = true;
     539           0 :                 break;
     540           0 :             default:
     541           0 :                 result = false;
     542           0 :                 break;
     543             :         }
     544             :     }
     545      527738 :     return result;
     546             : }
     547             : 
     548             : /*
     549             :  * transformDeleteStmt -
     550             :  *    transforms a Delete Statement
     551             :  */
     552             : static Query *
     553        4488 : transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
     554             : {
     555        4488 :     Query      *qry = makeNode(Query);
     556             :     ParseNamespaceItem *nsitem;
     557             :     Node       *qual;
     558             : 
     559        4488 :     qry->commandType = CMD_DELETE;
     560             : 
     561             :     /* process the WITH clause independently of all else */
     562        4488 :     if (stmt->withClause)
     563             :     {
     564          32 :         qry->hasRecursive = stmt->withClause->recursive;
     565          32 :         qry->cteList = transformWithClause(pstate, stmt->withClause);
     566          32 :         qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
     567             :     }
     568             : 
     569             :     /* set up range table with just the result rel */
     570        8970 :     qry->resultRelation = setTargetTable(pstate, stmt->relation,
     571        4488 :                                          stmt->relation->inh,
     572             :                                          true,
     573             :                                          ACL_DELETE);
     574        4482 :     nsitem = pstate->p_target_nsitem;
     575             : 
     576             :     /* there's no DISTINCT in DELETE */
     577        4482 :     qry->distinctClause = NIL;
     578             : 
     579             :     /* subqueries in USING cannot access the result relation */
     580        4482 :     nsitem->p_lateral_only = true;
     581        4482 :     nsitem->p_lateral_ok = false;
     582             : 
     583             :     /*
     584             :      * The USING clause is non-standard SQL syntax, and is equivalent in
     585             :      * functionality to the FROM list that can be specified for UPDATE. The
     586             :      * USING keyword is used rather than FROM because FROM is already a
     587             :      * keyword in the DELETE syntax.
     588             :      */
     589        4482 :     transformFromClause(pstate, stmt->usingClause);
     590             : 
     591             :     /* remaining clauses can reference the result relation normally */
     592        4464 :     nsitem->p_lateral_only = false;
     593        4464 :     nsitem->p_lateral_ok = true;
     594             : 
     595        4464 :     qual = transformWhereClause(pstate, stmt->whereClause,
     596             :                                 EXPR_KIND_WHERE, "WHERE");
     597             : 
     598        4440 :     transformReturningClause(pstate, qry, stmt->returningClause,
     599             :                              EXPR_KIND_RETURNING);
     600             : 
     601             :     /* done building the range table and jointree */
     602        4434 :     qry->rtable = pstate->p_rtable;
     603        4434 :     qry->rteperminfos = pstate->p_rteperminfos;
     604        4434 :     qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
     605             : 
     606        4434 :     qry->hasSubLinks = pstate->p_hasSubLinks;
     607        4434 :     qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
     608        4434 :     qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
     609        4434 :     qry->hasAggs = pstate->p_hasAggs;
     610             : 
     611        4434 :     assign_query_collations(pstate, qry);
     612             : 
     613             :     /* this must be done after collations, for reliable comparison of exprs */
     614        4434 :     if (pstate->p_hasAggs)
     615           0 :         parseCheckAggregates(pstate, qry);
     616             : 
     617        4434 :     return qry;
     618             : }
     619             : 
     620             : /*
     621             :  * transformInsertStmt -
     622             :  *    transform an Insert Statement
     623             :  */
     624             : static Query *
     625       68000 : transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
     626             : {
     627       68000 :     Query      *qry = makeNode(Query);
     628       68000 :     SelectStmt *selectStmt = (SelectStmt *) stmt->selectStmt;
     629       68000 :     List       *exprList = NIL;
     630             :     bool        isGeneralSelect;
     631             :     List       *sub_rtable;
     632             :     List       *sub_rteperminfos;
     633             :     List       *sub_namespace;
     634             :     List       *icolumns;
     635             :     List       *attrnos;
     636             :     ParseNamespaceItem *nsitem;
     637             :     RTEPermissionInfo *perminfo;
     638             :     ListCell   *icols;
     639             :     ListCell   *attnos;
     640             :     ListCell   *lc;
     641             :     bool        isOnConflictUpdate;
     642             :     AclMode     targetPerms;
     643             : 
     644             :     /* There can't be any outer WITH to worry about */
     645             :     Assert(pstate->p_ctenamespace == NIL);
     646             : 
     647       68000 :     qry->commandType = CMD_INSERT;
     648       68000 :     pstate->p_is_insert = true;
     649             : 
     650             :     /* process the WITH clause independently of all else */
     651       68000 :     if (stmt->withClause)
     652             :     {
     653         292 :         qry->hasRecursive = stmt->withClause->recursive;
     654         292 :         qry->cteList = transformWithClause(pstate, stmt->withClause);
     655         292 :         qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
     656             :     }
     657             : 
     658       68000 :     qry->override = stmt->override;
     659             : 
     660       69852 :     isOnConflictUpdate = (stmt->onConflictClause &&
     661        1852 :                           stmt->onConflictClause->action == ONCONFLICT_UPDATE);
     662             : 
     663             :     /*
     664             :      * We have three cases to deal with: DEFAULT VALUES (selectStmt == NULL),
     665             :      * VALUES list, or general SELECT input.  We special-case VALUES, both for
     666             :      * efficiency and so we can handle DEFAULT specifications.
     667             :      *
     668             :      * The grammar allows attaching ORDER BY, LIMIT, FOR UPDATE, or WITH to a
     669             :      * VALUES clause.  If we have any of those, treat it as a general SELECT;
     670             :      * so it will work, but you can't use DEFAULT items together with those.
     671             :      */
     672      118032 :     isGeneralSelect = (selectStmt && (selectStmt->valuesLists == NIL ||
     673       50032 :                                       selectStmt->sortClause != NIL ||
     674       50032 :                                       selectStmt->limitOffset != NULL ||
     675       50032 :                                       selectStmt->limitCount != NULL ||
     676       50032 :                                       selectStmt->lockingClause != NIL ||
     677       50032 :                                       selectStmt->withClause != NULL));
     678             : 
     679             :     /*
     680             :      * If a non-nil rangetable/namespace was passed in, and we are doing
     681             :      * INSERT/SELECT, arrange to pass the rangetable/rteperminfos/namespace
     682             :      * down to the SELECT.  This can only happen if we are inside a CREATE
     683             :      * RULE, and in that case we want the rule's OLD and NEW rtable entries to
     684             :      * appear as part of the SELECT's rtable, not as outer references for it.
     685             :      * (Kluge!) The SELECT's joinlist is not affected however.  We must do
     686             :      * this before adding the target table to the INSERT's rtable.
     687             :      */
     688       68000 :     if (isGeneralSelect)
     689             :     {
     690        7184 :         sub_rtable = pstate->p_rtable;
     691        7184 :         pstate->p_rtable = NIL;
     692        7184 :         sub_rteperminfos = pstate->p_rteperminfos;
     693        7184 :         pstate->p_rteperminfos = NIL;
     694        7184 :         sub_namespace = pstate->p_namespace;
     695        7184 :         pstate->p_namespace = NIL;
     696             :     }
     697             :     else
     698             :     {
     699       60816 :         sub_rtable = NIL;       /* not used, but keep compiler quiet */
     700       60816 :         sub_rteperminfos = NIL;
     701       60816 :         sub_namespace = NIL;
     702             :     }
     703             : 
     704             :     /*
     705             :      * Must get write lock on INSERT target table before scanning SELECT, else
     706             :      * we will grab the wrong kind of initial lock if the target table is also
     707             :      * mentioned in the SELECT part.  Note that the target table is not added
     708             :      * to the joinlist or namespace.
     709             :      */
     710       68000 :     targetPerms = ACL_INSERT;
     711       68000 :     if (isOnConflictUpdate)
     712        1302 :         targetPerms |= ACL_UPDATE;
     713       68000 :     qry->resultRelation = setTargetTable(pstate, stmt->relation,
     714             :                                          false, false, targetPerms);
     715             : 
     716             :     /* Validate stmt->cols list, or build default list if no list given */
     717       67982 :     icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
     718             :     Assert(list_length(icolumns) == list_length(attrnos));
     719             : 
     720             :     /*
     721             :      * Determine which variant of INSERT we have.
     722             :      */
     723       67934 :     if (selectStmt == NULL)
     724             :     {
     725             :         /*
     726             :          * We have INSERT ... DEFAULT VALUES.  We can handle this case by
     727             :          * emitting an empty targetlist --- all columns will be defaulted when
     728             :          * the planner expands the targetlist.
     729             :          */
     730       10784 :         exprList = NIL;
     731             :     }
     732       57150 :     else if (isGeneralSelect)
     733             :     {
     734             :         /*
     735             :          * We make the sub-pstate a child of the outer pstate so that it can
     736             :          * see any Param definitions supplied from above.  Since the outer
     737             :          * pstate's rtable and namespace are presently empty, there are no
     738             :          * side-effects of exposing names the sub-SELECT shouldn't be able to
     739             :          * see.
     740             :          */
     741        7184 :         ParseState *sub_pstate = make_parsestate(pstate);
     742             :         Query      *selectQuery;
     743             : 
     744             :         /*
     745             :          * Process the source SELECT.
     746             :          *
     747             :          * It is important that this be handled just like a standalone SELECT;
     748             :          * otherwise the behavior of SELECT within INSERT might be different
     749             :          * from a stand-alone SELECT. (Indeed, Postgres up through 6.5 had
     750             :          * bugs of just that nature...)
     751             :          *
     752             :          * The sole exception is that we prevent resolving unknown-type
     753             :          * outputs as TEXT.  This does not change the semantics since if the
     754             :          * column type matters semantically, it would have been resolved to
     755             :          * something else anyway.  Doing this lets us resolve such outputs as
     756             :          * the target column's type, which we handle below.
     757             :          */
     758        7184 :         sub_pstate->p_rtable = sub_rtable;
     759        7184 :         sub_pstate->p_rteperminfos = sub_rteperminfos;
     760        7184 :         sub_pstate->p_joinexprs = NIL;   /* sub_rtable has no joins */
     761        7184 :         sub_pstate->p_nullingrels = NIL;
     762        7184 :         sub_pstate->p_namespace = sub_namespace;
     763        7184 :         sub_pstate->p_resolve_unknowns = false;
     764             : 
     765        7184 :         selectQuery = transformStmt(sub_pstate, stmt->selectStmt);
     766             : 
     767        7178 :         free_parsestate(sub_pstate);
     768             : 
     769             :         /* The grammar should have produced a SELECT */
     770        7178 :         if (!IsA(selectQuery, Query) ||
     771        7178 :             selectQuery->commandType != CMD_SELECT)
     772           0 :             elog(ERROR, "unexpected non-SELECT command in INSERT ... SELECT");
     773             : 
     774             :         /*
     775             :          * Make the source be a subquery in the INSERT's rangetable, and add
     776             :          * it to the INSERT's joinlist (but not the namespace).
     777             :          */
     778        7178 :         nsitem = addRangeTableEntryForSubquery(pstate,
     779             :                                                selectQuery,
     780             :                                                makeAlias("*SELECT*", NIL),
     781             :                                                false,
     782             :                                                false);
     783        7178 :         addNSItemToQuery(pstate, nsitem, true, false, false);
     784             : 
     785             :         /*----------
     786             :          * Generate an expression list for the INSERT that selects all the
     787             :          * non-resjunk columns from the subquery.  (INSERT's tlist must be
     788             :          * separate from the subquery's tlist because we may add columns,
     789             :          * insert datatype coercions, etc.)
     790             :          *
     791             :          * HACK: unknown-type constants and params in the SELECT's targetlist
     792             :          * are copied up as-is rather than being referenced as subquery
     793             :          * outputs.  This is to ensure that when we try to coerce them to
     794             :          * the target column's datatype, the right things happen (see
     795             :          * special cases in coerce_type).  Otherwise, this fails:
     796             :          *      INSERT INTO foo SELECT 'bar', ... FROM baz
     797             :          *----------
     798             :          */
     799        7178 :         exprList = NIL;
     800       25382 :         foreach(lc, selectQuery->targetList)
     801             :         {
     802       18204 :             TargetEntry *tle = (TargetEntry *) lfirst(lc);
     803             :             Expr       *expr;
     804             : 
     805       18204 :             if (tle->resjunk)
     806         100 :                 continue;
     807       18104 :             if (tle->expr &&
     808       22618 :                 (IsA(tle->expr, Const) || IsA(tle->expr, Param)) &&
     809        4514 :                 exprType((Node *) tle->expr) == UNKNOWNOID)
     810        1378 :                 expr = tle->expr;
     811             :             else
     812             :             {
     813       16726 :                 Var        *var = makeVarFromTargetEntry(nsitem->p_rtindex, tle);
     814             : 
     815       16726 :                 var->location = exprLocation((Node *) tle->expr);
     816       16726 :                 expr = (Expr *) var;
     817             :             }
     818       18104 :             exprList = lappend(exprList, expr);
     819             :         }
     820             : 
     821             :         /* Prepare row for assignment to target table */
     822        7178 :         exprList = transformInsertRow(pstate, exprList,
     823             :                                       stmt->cols,
     824             :                                       icolumns, attrnos,
     825             :                                       false);
     826             :     }
     827       49966 :     else if (list_length(selectStmt->valuesLists) > 1)
     828             :     {
     829             :         /*
     830             :          * Process INSERT ... VALUES with multiple VALUES sublists. We
     831             :          * generate a VALUES RTE holding the transformed expression lists, and
     832             :          * build up a targetlist containing Vars that reference the VALUES
     833             :          * RTE.
     834             :          */
     835        4752 :         List       *exprsLists = NIL;
     836        4752 :         List       *coltypes = NIL;
     837        4752 :         List       *coltypmods = NIL;
     838        4752 :         List       *colcollations = NIL;
     839        4752 :         int         sublist_length = -1;
     840        4752 :         bool        lateral = false;
     841             : 
     842             :         Assert(selectStmt->intoClause == NULL);
     843             : 
     844       20034 :         foreach(lc, selectStmt->valuesLists)
     845             :         {
     846       15282 :             List       *sublist = (List *) lfirst(lc);
     847             : 
     848             :             /*
     849             :              * Do basic expression transformation (same as a ROW() expr, but
     850             :              * allow SetToDefault at top level)
     851             :              */
     852       15282 :             sublist = transformExpressionList(pstate, sublist,
     853             :                                               EXPR_KIND_VALUES, true);
     854             : 
     855             :             /*
     856             :              * All the sublists must be the same length, *after*
     857             :              * transformation (which might expand '*' into multiple items).
     858             :              * The VALUES RTE can't handle anything different.
     859             :              */
     860       15282 :             if (sublist_length < 0)
     861             :             {
     862             :                 /* Remember post-transformation length of first sublist */
     863        4752 :                 sublist_length = list_length(sublist);
     864             :             }
     865       10530 :             else if (sublist_length != list_length(sublist))
     866             :             {
     867           0 :                 ereport(ERROR,
     868             :                         (errcode(ERRCODE_SYNTAX_ERROR),
     869             :                          errmsg("VALUES lists must all be the same length"),
     870             :                          parser_errposition(pstate,
     871             :                                             exprLocation((Node *) sublist))));
     872             :             }
     873             : 
     874             :             /*
     875             :              * Prepare row for assignment to target table.  We process any
     876             :              * indirection on the target column specs normally but then strip
     877             :              * off the resulting field/array assignment nodes, since we don't
     878             :              * want the parsed statement to contain copies of those in each
     879             :              * VALUES row.  (It's annoying to have to transform the
     880             :              * indirection specs over and over like this, but avoiding it
     881             :              * would take some really messy refactoring of
     882             :              * transformAssignmentIndirection.)
     883             :              */
     884       15282 :             sublist = transformInsertRow(pstate, sublist,
     885             :                                          stmt->cols,
     886             :                                          icolumns, attrnos,
     887             :                                          true);
     888             : 
     889             :             /*
     890             :              * We must assign collations now because assign_query_collations
     891             :              * doesn't process rangetable entries.  We just assign all the
     892             :              * collations independently in each row, and don't worry about
     893             :              * whether they are consistent vertically.  The outer INSERT query
     894             :              * isn't going to care about the collations of the VALUES columns,
     895             :              * so it's not worth the effort to identify a common collation for
     896             :              * each one here.  (But note this does have one user-visible
     897             :              * consequence: INSERT ... VALUES won't complain about conflicting
     898             :              * explicit COLLATEs in a column, whereas the same VALUES
     899             :              * construct in another context would complain.)
     900             :              */
     901       15282 :             assign_list_collations(pstate, sublist);
     902             : 
     903       15282 :             exprsLists = lappend(exprsLists, sublist);
     904             :         }
     905             : 
     906             :         /*
     907             :          * Construct column type/typmod/collation lists for the VALUES RTE.
     908             :          * Every expression in each column has been coerced to the type/typmod
     909             :          * of the corresponding target column or subfield, so it's sufficient
     910             :          * to look at the exprType/exprTypmod of the first row.  We don't care
     911             :          * about the collation labeling, so just fill in InvalidOid for that.
     912             :          */
     913       13294 :         foreach(lc, (List *) linitial(exprsLists))
     914             :         {
     915        8542 :             Node       *val = (Node *) lfirst(lc);
     916             : 
     917        8542 :             coltypes = lappend_oid(coltypes, exprType(val));
     918        8542 :             coltypmods = lappend_int(coltypmods, exprTypmod(val));
     919        8542 :             colcollations = lappend_oid(colcollations, InvalidOid);
     920             :         }
     921             : 
     922             :         /*
     923             :          * Ordinarily there can't be any current-level Vars in the expression
     924             :          * lists, because the namespace was empty ... but if we're inside
     925             :          * CREATE RULE, then NEW/OLD references might appear.  In that case we
     926             :          * have to mark the VALUES RTE as LATERAL.
     927             :          */
     928        4784 :         if (list_length(pstate->p_rtable) != 1 &&
     929          32 :             contain_vars_of_level((Node *) exprsLists, 0))
     930          32 :             lateral = true;
     931             : 
     932             :         /*
     933             :          * Generate the VALUES RTE
     934             :          */
     935        4752 :         nsitem = addRangeTableEntryForValues(pstate, exprsLists,
     936             :                                              coltypes, coltypmods, colcollations,
     937             :                                              NULL, lateral, true);
     938        4752 :         addNSItemToQuery(pstate, nsitem, true, false, false);
     939             : 
     940             :         /*
     941             :          * Generate list of Vars referencing the RTE
     942             :          */
     943        4752 :         exprList = expandNSItemVars(pstate, nsitem, 0, -1, NULL);
     944             : 
     945             :         /*
     946             :          * Re-apply any indirection on the target column specs to the Vars
     947             :          */
     948        4752 :         exprList = transformInsertRow(pstate, exprList,
     949             :                                       stmt->cols,
     950             :                                       icolumns, attrnos,
     951             :                                       false);
     952             :     }
     953             :     else
     954             :     {
     955             :         /*
     956             :          * Process INSERT ... VALUES with a single VALUES sublist.  We treat
     957             :          * this case separately for efficiency.  The sublist is just computed
     958             :          * directly as the Query's targetlist, with no VALUES RTE.  So it
     959             :          * works just like a SELECT without any FROM.
     960             :          */
     961       45214 :         List       *valuesLists = selectStmt->valuesLists;
     962             : 
     963             :         Assert(list_length(valuesLists) == 1);
     964             :         Assert(selectStmt->intoClause == NULL);
     965             : 
     966             :         /*
     967             :          * Do basic expression transformation (same as a ROW() expr, but allow
     968             :          * SetToDefault at top level)
     969             :          */
     970       45214 :         exprList = transformExpressionList(pstate,
     971       45214 :                                            (List *) linitial(valuesLists),
     972             :                                            EXPR_KIND_VALUES_SINGLE,
     973             :                                            true);
     974             : 
     975             :         /* Prepare row for assignment to target table */
     976       45190 :         exprList = transformInsertRow(pstate, exprList,
     977             :                                       stmt->cols,
     978             :                                       icolumns, attrnos,
     979             :                                       false);
     980             :     }
     981             : 
     982             :     /*
     983             :      * Generate query's target list using the computed list of expressions.
     984             :      * Also, mark all the target columns as needing insert permissions.
     985             :      */
     986       66674 :     perminfo = pstate->p_target_nsitem->p_perminfo;
     987       66674 :     qry->targetList = NIL;
     988             :     Assert(list_length(exprList) <= list_length(icolumns));
     989      192134 :     forthree(lc, exprList, icols, icolumns, attnos, attrnos)
     990             :     {
     991      125460 :         Expr       *expr = (Expr *) lfirst(lc);
     992      125460 :         ResTarget  *col = lfirst_node(ResTarget, icols);
     993      125460 :         AttrNumber  attr_num = (AttrNumber) lfirst_int(attnos);
     994             :         TargetEntry *tle;
     995             : 
     996      125460 :         tle = makeTargetEntry(expr,
     997             :                               attr_num,
     998             :                               col->name,
     999             :                               false);
    1000      125460 :         qry->targetList = lappend(qry->targetList, tle);
    1001             : 
    1002      125460 :         perminfo->insertedCols = bms_add_member(perminfo->insertedCols,
    1003             :                                                 attr_num - FirstLowInvalidHeapAttributeNumber);
    1004             :     }
    1005             : 
    1006             :     /*
    1007             :      * If we have any clauses yet to process, set the query namespace to
    1008             :      * contain only the target relation, removing any entries added in a
    1009             :      * sub-SELECT or VALUES list.
    1010             :      */
    1011       66674 :     if (stmt->onConflictClause || stmt->returningClause)
    1012             :     {
    1013        2814 :         pstate->p_namespace = NIL;
    1014        2814 :         addNSItemToQuery(pstate, pstate->p_target_nsitem,
    1015             :                          false, true, true);
    1016             :     }
    1017             : 
    1018             :     /* Process ON CONFLICT, if any. */
    1019       66674 :     if (stmt->onConflictClause)
    1020        1852 :         qry->onConflict = transformOnConflictClause(pstate,
    1021             :                                                     stmt->onConflictClause);
    1022             : 
    1023             :     /* Process RETURNING, if any. */
    1024       66632 :     if (stmt->returningClause)
    1025        1240 :         transformReturningClause(pstate, qry, stmt->returningClause,
    1026             :                                  EXPR_KIND_RETURNING);
    1027             : 
    1028             :     /* done building the range table and jointree */
    1029       66584 :     qry->rtable = pstate->p_rtable;
    1030       66584 :     qry->rteperminfos = pstate->p_rteperminfos;
    1031       66584 :     qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
    1032             : 
    1033       66584 :     qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
    1034       66584 :     qry->hasSubLinks = pstate->p_hasSubLinks;
    1035             : 
    1036       66584 :     assign_query_collations(pstate, qry);
    1037             : 
    1038       66584 :     return qry;
    1039             : }
    1040             : 
    1041             : /*
    1042             :  * Prepare an INSERT row for assignment to the target table.
    1043             :  *
    1044             :  * exprlist: transformed expressions for source values; these might come from
    1045             :  * a VALUES row, or be Vars referencing a sub-SELECT or VALUES RTE output.
    1046             :  * stmtcols: original target-columns spec for INSERT (we just test for NIL)
    1047             :  * icolumns: effective target-columns spec (list of ResTarget)
    1048             :  * attrnos: integer column numbers (must be same length as icolumns)
    1049             :  * strip_indirection: if true, remove any field/array assignment nodes
    1050             :  */
    1051             : List *
    1052       73376 : transformInsertRow(ParseState *pstate, List *exprlist,
    1053             :                    List *stmtcols, List *icolumns, List *attrnos,
    1054             :                    bool strip_indirection)
    1055             : {
    1056             :     List       *result;
    1057             :     ListCell   *lc;
    1058             :     ListCell   *icols;
    1059             :     ListCell   *attnos;
    1060             : 
    1061             :     /*
    1062             :      * Check length of expr list.  It must not have more expressions than
    1063             :      * there are target columns.  We allow fewer, but only if no explicit
    1064             :      * columns list was given (the remaining columns are implicitly
    1065             :      * defaulted).  Note we must check this *after* transformation because
    1066             :      * that could expand '*' into multiple items.
    1067             :      */
    1068       73376 :     if (list_length(exprlist) > list_length(icolumns))
    1069          26 :         ereport(ERROR,
    1070             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    1071             :                  errmsg("INSERT has more expressions than target columns"),
    1072             :                  parser_errposition(pstate,
    1073             :                                     exprLocation(list_nth(exprlist,
    1074             :                                                           list_length(icolumns))))));
    1075       90048 :     if (stmtcols != NIL &&
    1076       16698 :         list_length(exprlist) < list_length(icolumns))
    1077             :     {
    1078             :         /*
    1079             :          * We can get here for cases like INSERT ... SELECT (a,b,c) FROM ...
    1080             :          * where the user accidentally created a RowExpr instead of separate
    1081             :          * columns.  Add a suitable hint if that seems to be the problem,
    1082             :          * because the main error message is quite misleading for this case.
    1083             :          * (If there's no stmtcols, you'll get something about data type
    1084             :          * mismatch, which is less misleading so we don't worry about giving a
    1085             :          * hint in that case.)
    1086             :          */
    1087          12 :         ereport(ERROR,
    1088             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    1089             :                  errmsg("INSERT has more target columns than expressions"),
    1090             :                  ((list_length(exprlist) == 1 &&
    1091             :                    count_rowexpr_columns(pstate, linitial(exprlist)) ==
    1092             :                    list_length(icolumns)) ?
    1093             :                   errhint("The insertion source is a row expression containing the same number of columns expected by the INSERT. Did you accidentally use extra parentheses?") : 0),
    1094             :                  parser_errposition(pstate,
    1095             :                                     exprLocation(list_nth(icolumns,
    1096             :                                                           list_length(exprlist))))));
    1097             :     }
    1098             : 
    1099             :     /*
    1100             :      * Prepare columns for assignment to target table.
    1101             :      */
    1102       73338 :     result = NIL;
    1103      230928 :     forthree(lc, exprlist, icols, icolumns, attnos, attrnos)
    1104             :     {
    1105      158782 :         Expr       *expr = (Expr *) lfirst(lc);
    1106      158782 :         ResTarget  *col = lfirst_node(ResTarget, icols);
    1107      158782 :         int         attno = lfirst_int(attnos);
    1108             : 
    1109      158782 :         expr = transformAssignedExpr(pstate, expr,
    1110             :                                      EXPR_KIND_INSERT_TARGET,
    1111      158782 :                                      col->name,
    1112             :                                      attno,
    1113             :                                      col->indirection,
    1114             :                                      col->location);
    1115             : 
    1116      157590 :         if (strip_indirection)
    1117             :         {
    1118             :             /*
    1119             :              * We need to remove top-level FieldStores and SubscriptingRefs,
    1120             :              * as well as any CoerceToDomain appearing above one of those ---
    1121             :              * but not a CoerceToDomain that isn't above one of those.
    1122             :              */
    1123       30438 :             while (expr)
    1124             :             {
    1125       30438 :                 Expr       *subexpr = expr;
    1126             : 
    1127       30654 :                 while (IsA(subexpr, CoerceToDomain))
    1128             :                 {
    1129         216 :                     subexpr = ((CoerceToDomain *) subexpr)->arg;
    1130             :                 }
    1131       30438 :                 if (IsA(subexpr, FieldStore))
    1132             :                 {
    1133         216 :                     FieldStore *fstore = (FieldStore *) subexpr;
    1134             : 
    1135         216 :                     expr = (Expr *) linitial(fstore->newvals);
    1136             :                 }
    1137       30222 :                 else if (IsA(subexpr, SubscriptingRef))
    1138             :                 {
    1139         348 :                     SubscriptingRef *sbsref = (SubscriptingRef *) subexpr;
    1140             : 
    1141         348 :                     if (sbsref->refassgnexpr == NULL)
    1142           0 :                         break;
    1143             : 
    1144         348 :                     expr = sbsref->refassgnexpr;
    1145             :                 }
    1146             :                 else
    1147       29874 :                     break;
    1148             :             }
    1149             :         }
    1150             : 
    1151      157590 :         result = lappend(result, expr);
    1152             :     }
    1153             : 
    1154       72146 :     return result;
    1155             : }
    1156             : 
    1157             : /*
    1158             :  * transformOnConflictClause -
    1159             :  *    transforms an OnConflictClause in an INSERT
    1160             :  */
    1161             : static OnConflictExpr *
    1162        1852 : transformOnConflictClause(ParseState *pstate,
    1163             :                           OnConflictClause *onConflictClause)
    1164             : {
    1165        1852 :     ParseNamespaceItem *exclNSItem = NULL;
    1166             :     List       *arbiterElems;
    1167             :     Node       *arbiterWhere;
    1168             :     Oid         arbiterConstraint;
    1169        1852 :     List       *onConflictSet = NIL;
    1170        1852 :     Node       *onConflictWhere = NULL;
    1171        1852 :     int         exclRelIndex = 0;
    1172        1852 :     List       *exclRelTlist = NIL;
    1173             :     OnConflictExpr *result;
    1174             : 
    1175             :     /*
    1176             :      * If this is ON CONFLICT ... UPDATE, first create the range table entry
    1177             :      * for the EXCLUDED pseudo relation, so that that will be present while
    1178             :      * processing arbiter expressions.  (You can't actually reference it from
    1179             :      * there, but this provides a useful error message if you try.)
    1180             :      */
    1181        1852 :     if (onConflictClause->action == ONCONFLICT_UPDATE)
    1182             :     {
    1183        1302 :         Relation    targetrel = pstate->p_target_relation;
    1184             :         RangeTblEntry *exclRte;
    1185             : 
    1186        1302 :         exclNSItem = addRangeTableEntryForRelation(pstate,
    1187             :                                                    targetrel,
    1188             :                                                    RowExclusiveLock,
    1189             :                                                    makeAlias("excluded", NIL),
    1190             :                                                    false, false);
    1191        1302 :         exclRte = exclNSItem->p_rte;
    1192        1302 :         exclRelIndex = exclNSItem->p_rtindex;
    1193             : 
    1194             :         /*
    1195             :          * relkind is set to composite to signal that we're not dealing with
    1196             :          * an actual relation, and no permission checks are required on it.
    1197             :          * (We'll check the actual target relation, instead.)
    1198             :          */
    1199        1302 :         exclRte->relkind = RELKIND_COMPOSITE_TYPE;
    1200             : 
    1201             :         /* Create EXCLUDED rel's targetlist for use by EXPLAIN */
    1202        1302 :         exclRelTlist = BuildOnConflictExcludedTargetlist(targetrel,
    1203             :                                                          exclRelIndex);
    1204             :     }
    1205             : 
    1206             :     /* Process the arbiter clause, ON CONFLICT ON (...) */
    1207        1852 :     transformOnConflictArbiter(pstate, onConflictClause, &arbiterElems,
    1208             :                                &arbiterWhere, &arbiterConstraint);
    1209             : 
    1210             :     /* Process DO UPDATE */
    1211        1840 :     if (onConflictClause->action == ONCONFLICT_UPDATE)
    1212             :     {
    1213             :         /*
    1214             :          * Expressions in the UPDATE targetlist need to be handled like UPDATE
    1215             :          * not INSERT.  We don't need to save/restore this because all INSERT
    1216             :          * expressions have been parsed already.
    1217             :          */
    1218        1290 :         pstate->p_is_insert = false;
    1219             : 
    1220             :         /*
    1221             :          * Add the EXCLUDED pseudo relation to the query namespace, making it
    1222             :          * available in the UPDATE subexpressions.
    1223             :          */
    1224        1290 :         addNSItemToQuery(pstate, exclNSItem, false, true, true);
    1225             : 
    1226             :         /*
    1227             :          * Now transform the UPDATE subexpressions.
    1228             :          */
    1229             :         onConflictSet =
    1230        1290 :             transformUpdateTargetList(pstate, onConflictClause->targetList);
    1231             : 
    1232        1260 :         onConflictWhere = transformWhereClause(pstate,
    1233             :                                                onConflictClause->whereClause,
    1234             :                                                EXPR_KIND_WHERE, "WHERE");
    1235             : 
    1236             :         /*
    1237             :          * Remove the EXCLUDED pseudo relation from the query namespace, since
    1238             :          * it's not supposed to be available in RETURNING.  (Maybe someday we
    1239             :          * could allow that, and drop this step.)
    1240             :          */
    1241             :         Assert((ParseNamespaceItem *) llast(pstate->p_namespace) == exclNSItem);
    1242        1260 :         pstate->p_namespace = list_delete_last(pstate->p_namespace);
    1243             :     }
    1244             : 
    1245             :     /* Finally, build ON CONFLICT DO [NOTHING | UPDATE] expression */
    1246        1810 :     result = makeNode(OnConflictExpr);
    1247             : 
    1248        1810 :     result->action = onConflictClause->action;
    1249        1810 :     result->arbiterElems = arbiterElems;
    1250        1810 :     result->arbiterWhere = arbiterWhere;
    1251        1810 :     result->constraint = arbiterConstraint;
    1252        1810 :     result->onConflictSet = onConflictSet;
    1253        1810 :     result->onConflictWhere = onConflictWhere;
    1254        1810 :     result->exclRelIndex = exclRelIndex;
    1255        1810 :     result->exclRelTlist = exclRelTlist;
    1256             : 
    1257        1810 :     return result;
    1258             : }
    1259             : 
    1260             : 
    1261             : /*
    1262             :  * BuildOnConflictExcludedTargetlist
    1263             :  *      Create target list for the EXCLUDED pseudo-relation of ON CONFLICT,
    1264             :  *      representing the columns of targetrel with varno exclRelIndex.
    1265             :  *
    1266             :  * Note: Exported for use in the rewriter.
    1267             :  */
    1268             : List *
    1269        1446 : BuildOnConflictExcludedTargetlist(Relation targetrel,
    1270             :                                   Index exclRelIndex)
    1271             : {
    1272        1446 :     List       *result = NIL;
    1273             :     int         attno;
    1274             :     Var        *var;
    1275             :     TargetEntry *te;
    1276             : 
    1277             :     /*
    1278             :      * Note that resnos of the tlist must correspond to attnos of the
    1279             :      * underlying relation, hence we need entries for dropped columns too.
    1280             :      */
    1281        5140 :     for (attno = 0; attno < RelationGetNumberOfAttributes(targetrel); attno++)
    1282             :     {
    1283        3694 :         Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno);
    1284             :         char       *name;
    1285             : 
    1286        3694 :         if (attr->attisdropped)
    1287             :         {
    1288             :             /*
    1289             :              * can't use atttypid here, but it doesn't really matter what type
    1290             :              * the Const claims to be.
    1291             :              */
    1292          64 :             var = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
    1293          64 :             name = NULL;
    1294             :         }
    1295             :         else
    1296             :         {
    1297        3630 :             var = makeVar(exclRelIndex, attno + 1,
    1298             :                           attr->atttypid, attr->atttypmod,
    1299             :                           attr->attcollation,
    1300             :                           0);
    1301        3630 :             name = pstrdup(NameStr(attr->attname));
    1302             :         }
    1303             : 
    1304        3694 :         te = makeTargetEntry((Expr *) var,
    1305        3694 :                              attno + 1,
    1306             :                              name,
    1307             :                              false);
    1308             : 
    1309        3694 :         result = lappend(result, te);
    1310             :     }
    1311             : 
    1312             :     /*
    1313             :      * Add a whole-row-Var entry to support references to "EXCLUDED.*".  Like
    1314             :      * the other entries in the EXCLUDED tlist, its resno must match the Var's
    1315             :      * varattno, else the wrong things happen while resolving references in
    1316             :      * setrefs.c.  This is against normal conventions for targetlists, but
    1317             :      * it's okay since we don't use this as a real tlist.
    1318             :      */
    1319        1446 :     var = makeVar(exclRelIndex, InvalidAttrNumber,
    1320        1446 :                   targetrel->rd_rel->reltype,
    1321             :                   -1, InvalidOid, 0);
    1322        1446 :     te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
    1323        1446 :     result = lappend(result, te);
    1324             : 
    1325        1446 :     return result;
    1326             : }
    1327             : 
    1328             : 
    1329             : /*
    1330             :  * count_rowexpr_columns -
    1331             :  *    get number of columns contained in a ROW() expression;
    1332             :  *    return -1 if expression isn't a RowExpr or a Var referencing one.
    1333             :  *
    1334             :  * This is currently used only for hint purposes, so we aren't terribly
    1335             :  * tense about recognizing all possible cases.  The Var case is interesting
    1336             :  * because that's what we'll get in the INSERT ... SELECT (...) case.
    1337             :  */
    1338             : static int
    1339           0 : count_rowexpr_columns(ParseState *pstate, Node *expr)
    1340             : {
    1341           0 :     if (expr == NULL)
    1342           0 :         return -1;
    1343           0 :     if (IsA(expr, RowExpr))
    1344           0 :         return list_length(((RowExpr *) expr)->args);
    1345           0 :     if (IsA(expr, Var))
    1346             :     {
    1347           0 :         Var        *var = (Var *) expr;
    1348           0 :         AttrNumber  attnum = var->varattno;
    1349             : 
    1350           0 :         if (attnum > 0 && var->vartype == RECORDOID)
    1351             :         {
    1352             :             RangeTblEntry *rte;
    1353             : 
    1354           0 :             rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup);
    1355           0 :             if (rte->rtekind == RTE_SUBQUERY)
    1356             :             {
    1357             :                 /* Subselect-in-FROM: examine sub-select's output expr */
    1358           0 :                 TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList,
    1359             :                                                     attnum);
    1360             : 
    1361           0 :                 if (ste == NULL || ste->resjunk)
    1362           0 :                     return -1;
    1363           0 :                 expr = (Node *) ste->expr;
    1364           0 :                 if (IsA(expr, RowExpr))
    1365           0 :                     return list_length(((RowExpr *) expr)->args);
    1366             :             }
    1367             :         }
    1368             :     }
    1369           0 :     return -1;
    1370             : }
    1371             : 
    1372             : 
    1373             : /*
    1374             :  * transformSelectStmt -
    1375             :  *    transforms a Select Statement
    1376             :  *
    1377             :  * Note: this covers only cases with no set operations and no VALUES lists;
    1378             :  * see below for the other cases.
    1379             :  */
    1380             : static Query *
    1381      460184 : transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
    1382             : {
    1383      460184 :     Query      *qry = makeNode(Query);
    1384             :     Node       *qual;
    1385             :     ListCell   *l;
    1386             : 
    1387      460184 :     qry->commandType = CMD_SELECT;
    1388             : 
    1389             :     /* process the WITH clause independently of all else */
    1390      460184 :     if (stmt->withClause)
    1391             :     {
    1392        2590 :         qry->hasRecursive = stmt->withClause->recursive;
    1393        2590 :         qry->cteList = transformWithClause(pstate, stmt->withClause);
    1394        2294 :         qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
    1395             :     }
    1396             : 
    1397             :     /* Complain if we get called from someplace where INTO is not allowed */
    1398      459888 :     if (stmt->intoClause)
    1399          18 :         ereport(ERROR,
    1400             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    1401             :                  errmsg("SELECT ... INTO is not allowed here"),
    1402             :                  parser_errposition(pstate,
    1403             :                                     exprLocation((Node *) stmt->intoClause))));
    1404             : 
    1405             :     /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
    1406      459870 :     pstate->p_locking_clause = stmt->lockingClause;
    1407             : 
    1408             :     /* make WINDOW info available for window functions, too */
    1409      459870 :     pstate->p_windowdefs = stmt->windowClause;
    1410             : 
    1411             :     /* process the FROM clause */
    1412      459870 :     transformFromClause(pstate, stmt->fromClause);
    1413             : 
    1414             :     /* transform targetlist */
    1415      459242 :     qry->targetList = transformTargetList(pstate, stmt->targetList,
    1416             :                                           EXPR_KIND_SELECT_TARGET);
    1417             : 
    1418             :     /* mark column origins */
    1419      454442 :     markTargetListOrigins(pstate, qry->targetList);
    1420             : 
    1421             :     /* transform WHERE */
    1422      454442 :     qual = transformWhereClause(pstate, stmt->whereClause,
    1423             :                                 EXPR_KIND_WHERE, "WHERE");
    1424             : 
    1425             :     /* initial processing of HAVING clause is much like WHERE clause */
    1426      454334 :     qry->havingQual = transformWhereClause(pstate, stmt->havingClause,
    1427             :                                            EXPR_KIND_HAVING, "HAVING");
    1428             : 
    1429             :     /*
    1430             :      * Transform sorting/grouping stuff.  Do ORDER BY first because both
    1431             :      * transformGroupClause and transformDistinctClause need the results. Note
    1432             :      * that these functions can also change the targetList, so it's passed to
    1433             :      * them by reference.
    1434             :      */
    1435      454328 :     qry->sortClause = transformSortClause(pstate,
    1436             :                                           stmt->sortClause,
    1437             :                                           &qry->targetList,
    1438             :                                           EXPR_KIND_ORDER_BY,
    1439             :                                           false /* allow SQL92 rules */ );
    1440             : 
    1441      454298 :     qry->groupClause = transformGroupClause(pstate,
    1442             :                                             stmt->groupClause,
    1443             :                                             &qry->groupingSets,
    1444             :                                             &qry->targetList,
    1445             :                                             qry->sortClause,
    1446             :                                             EXPR_KIND_GROUP_BY,
    1447             :                                             false /* allow SQL92 rules */ );
    1448      454274 :     qry->groupDistinct = stmt->groupDistinct;
    1449             : 
    1450      454274 :     if (stmt->distinctClause == NIL)
    1451             :     {
    1452      450542 :         qry->distinctClause = NIL;
    1453      450542 :         qry->hasDistinctOn = false;
    1454             :     }
    1455        3732 :     else if (linitial(stmt->distinctClause) == NULL)
    1456             :     {
    1457             :         /* We had SELECT DISTINCT */
    1458        3474 :         qry->distinctClause = transformDistinctClause(pstate,
    1459             :                                                       &qry->targetList,
    1460             :                                                       qry->sortClause,
    1461             :                                                       false);
    1462        3474 :         qry->hasDistinctOn = false;
    1463             :     }
    1464             :     else
    1465             :     {
    1466             :         /* We had SELECT DISTINCT ON */
    1467         258 :         qry->distinctClause = transformDistinctOnClause(pstate,
    1468             :                                                         stmt->distinctClause,
    1469             :                                                         &qry->targetList,
    1470             :                                                         qry->sortClause);
    1471         246 :         qry->hasDistinctOn = true;
    1472             :     }
    1473             : 
    1474             :     /* transform LIMIT */
    1475      454262 :     qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
    1476             :                                             EXPR_KIND_OFFSET, "OFFSET",
    1477             :                                             stmt->limitOption);
    1478      454262 :     qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
    1479             :                                            EXPR_KIND_LIMIT, "LIMIT",
    1480             :                                            stmt->limitOption);
    1481      454250 :     qry->limitOption = stmt->limitOption;
    1482             : 
    1483             :     /* transform window clauses after we have seen all window functions */
    1484      454250 :     qry->windowClause = transformWindowDefinitions(pstate,
    1485             :                                                    pstate->p_windowdefs,
    1486             :                                                    &qry->targetList);
    1487             : 
    1488             :     /* resolve any still-unresolved output columns as being type text */
    1489      454184 :     if (pstate->p_resolve_unknowns)
    1490      418494 :         resolveTargetListUnknowns(pstate, qry->targetList);
    1491             : 
    1492      454184 :     qry->rtable = pstate->p_rtable;
    1493      454184 :     qry->rteperminfos = pstate->p_rteperminfos;
    1494      454184 :     qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
    1495             : 
    1496      454184 :     qry->hasSubLinks = pstate->p_hasSubLinks;
    1497      454184 :     qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
    1498      454184 :     qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
    1499      454184 :     qry->hasAggs = pstate->p_hasAggs;
    1500             : 
    1501      459364 :     foreach(l, stmt->lockingClause)
    1502             :     {
    1503        5222 :         transformLockingClause(pstate, qry,
    1504        5222 :                                (LockingClause *) lfirst(l), false);
    1505             :     }
    1506             : 
    1507      454142 :     assign_query_collations(pstate, qry);
    1508             : 
    1509             :     /* this must be done after collations, for reliable comparison of exprs */
    1510      454100 :     if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
    1511       37282 :         parseCheckAggregates(pstate, qry);
    1512             : 
    1513      453992 :     return qry;
    1514             : }
    1515             : 
    1516             : /*
    1517             :  * transformValuesClause -
    1518             :  *    transforms a VALUES clause that's being used as a standalone SELECT
    1519             :  *
    1520             :  * We build a Query containing a VALUES RTE, rather as if one had written
    1521             :  *          SELECT * FROM (VALUES ...) AS "*VALUES*"
    1522             :  */
    1523             : static Query *
    1524        8464 : transformValuesClause(ParseState *pstate, SelectStmt *stmt)
    1525             : {
    1526        8464 :     Query      *qry = makeNode(Query);
    1527        8464 :     List       *exprsLists = NIL;
    1528        8464 :     List       *coltypes = NIL;
    1529        8464 :     List       *coltypmods = NIL;
    1530        8464 :     List       *colcollations = NIL;
    1531        8464 :     List      **colexprs = NULL;
    1532        8464 :     int         sublist_length = -1;
    1533        8464 :     bool        lateral = false;
    1534             :     ParseNamespaceItem *nsitem;
    1535             :     ListCell   *lc;
    1536             :     ListCell   *lc2;
    1537             :     int         i;
    1538             : 
    1539        8464 :     qry->commandType = CMD_SELECT;
    1540             : 
    1541             :     /* Most SELECT stuff doesn't apply in a VALUES clause */
    1542             :     Assert(stmt->distinctClause == NIL);
    1543             :     Assert(stmt->intoClause == NULL);
    1544             :     Assert(stmt->targetList == NIL);
    1545             :     Assert(stmt->fromClause == NIL);
    1546             :     Assert(stmt->whereClause == NULL);
    1547             :     Assert(stmt->groupClause == NIL);
    1548             :     Assert(stmt->havingClause == NULL);
    1549             :     Assert(stmt->windowClause == NIL);
    1550             :     Assert(stmt->op == SETOP_NONE);
    1551             : 
    1552             :     /* process the WITH clause independently of all else */
    1553        8464 :     if (stmt->withClause)
    1554             :     {
    1555          60 :         qry->hasRecursive = stmt->withClause->recursive;
    1556          60 :         qry->cteList = transformWithClause(pstate, stmt->withClause);
    1557          54 :         qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
    1558             :     }
    1559             : 
    1560             :     /*
    1561             :      * For each row of VALUES, transform the raw expressions.
    1562             :      *
    1563             :      * Note that the intermediate representation we build is column-organized
    1564             :      * not row-organized.  That simplifies the type and collation processing
    1565             :      * below.
    1566             :      */
    1567       31444 :     foreach(lc, stmt->valuesLists)
    1568             :     {
    1569       22994 :         List       *sublist = (List *) lfirst(lc);
    1570             : 
    1571             :         /*
    1572             :          * Do basic expression transformation (same as a ROW() expr, but here
    1573             :          * we disallow SetToDefault)
    1574             :          */
    1575       22994 :         sublist = transformExpressionList(pstate, sublist,
    1576             :                                           EXPR_KIND_VALUES, false);
    1577             : 
    1578             :         /*
    1579             :          * All the sublists must be the same length, *after* transformation
    1580             :          * (which might expand '*' into multiple items).  The VALUES RTE can't
    1581             :          * handle anything different.
    1582             :          */
    1583       22986 :         if (sublist_length < 0)
    1584             :         {
    1585             :             /* Remember post-transformation length of first sublist */
    1586        8450 :             sublist_length = list_length(sublist);
    1587             :             /* and allocate array for per-column lists */
    1588        8450 :             colexprs = (List **) palloc0(sublist_length * sizeof(List *));
    1589             :         }
    1590       14536 :         else if (sublist_length != list_length(sublist))
    1591             :         {
    1592           0 :             ereport(ERROR,
    1593             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    1594             :                      errmsg("VALUES lists must all be the same length"),
    1595             :                      parser_errposition(pstate,
    1596             :                                         exprLocation((Node *) sublist))));
    1597             :         }
    1598             : 
    1599             :         /* Build per-column expression lists */
    1600       22986 :         i = 0;
    1601       55100 :         foreach(lc2, sublist)
    1602             :         {
    1603       32114 :             Node       *col = (Node *) lfirst(lc2);
    1604             : 
    1605       32114 :             colexprs[i] = lappend(colexprs[i], col);
    1606       32114 :             i++;
    1607             :         }
    1608             : 
    1609             :         /* Release sub-list's cells to save memory */
    1610       22986 :         list_free(sublist);
    1611             : 
    1612             :         /* Prepare an exprsLists element for this row */
    1613       22986 :         exprsLists = lappend(exprsLists, NIL);
    1614             :     }
    1615             : 
    1616             :     /*
    1617             :      * Now resolve the common types of the columns, and coerce everything to
    1618             :      * those types.  Then identify the common typmod and common collation, if
    1619             :      * any, of each column.
    1620             :      *
    1621             :      * We must do collation processing now because (1) assign_query_collations
    1622             :      * doesn't process rangetable entries, and (2) we need to label the VALUES
    1623             :      * RTE with column collations for use in the outer query.  We don't
    1624             :      * consider conflict of implicit collations to be an error here; instead
    1625             :      * the column will just show InvalidOid as its collation, and you'll get a
    1626             :      * failure later if that results in failure to resolve a collation.
    1627             :      *
    1628             :      * Note we modify the per-column expression lists in-place.
    1629             :      */
    1630       19572 :     for (i = 0; i < sublist_length; i++)
    1631             :     {
    1632             :         Oid         coltype;
    1633             :         int32       coltypmod;
    1634             :         Oid         colcoll;
    1635             : 
    1636       11122 :         coltype = select_common_type(pstate, colexprs[i], "VALUES", NULL);
    1637             : 
    1638       43236 :         foreach(lc, colexprs[i])
    1639             :         {
    1640       32114 :             Node       *col = (Node *) lfirst(lc);
    1641             : 
    1642       32114 :             col = coerce_to_common_type(pstate, col, coltype, "VALUES");
    1643       32114 :             lfirst(lc) = col;
    1644             :         }
    1645             : 
    1646       11122 :         coltypmod = select_common_typmod(pstate, colexprs[i], coltype);
    1647       11122 :         colcoll = select_common_collation(pstate, colexprs[i], true);
    1648             : 
    1649       11122 :         coltypes = lappend_oid(coltypes, coltype);
    1650       11122 :         coltypmods = lappend_int(coltypmods, coltypmod);
    1651       11122 :         colcollations = lappend_oid(colcollations, colcoll);
    1652             :     }
    1653             : 
    1654             :     /*
    1655             :      * Finally, rearrange the coerced expressions into row-organized lists.
    1656             :      */
    1657       19572 :     for (i = 0; i < sublist_length; i++)
    1658             :     {
    1659       43236 :         forboth(lc, colexprs[i], lc2, exprsLists)
    1660             :         {
    1661       32114 :             Node       *col = (Node *) lfirst(lc);
    1662       32114 :             List       *sublist = lfirst(lc2);
    1663             : 
    1664       32114 :             sublist = lappend(sublist, col);
    1665       32114 :             lfirst(lc2) = sublist;
    1666             :         }
    1667       11122 :         list_free(colexprs[i]);
    1668             :     }
    1669             : 
    1670             :     /*
    1671             :      * Ordinarily there can't be any current-level Vars in the expression
    1672             :      * lists, because the namespace was empty ... but if we're inside CREATE
    1673             :      * RULE, then NEW/OLD references might appear.  In that case we have to
    1674             :      * mark the VALUES RTE as LATERAL.
    1675             :      */
    1676        8460 :     if (pstate->p_rtable != NIL &&
    1677          10 :         contain_vars_of_level((Node *) exprsLists, 0))
    1678          10 :         lateral = true;
    1679             : 
    1680             :     /*
    1681             :      * Generate the VALUES RTE
    1682             :      */
    1683        8450 :     nsitem = addRangeTableEntryForValues(pstate, exprsLists,
    1684             :                                          coltypes, coltypmods, colcollations,
    1685             :                                          NULL, lateral, true);
    1686        8450 :     addNSItemToQuery(pstate, nsitem, true, true, true);
    1687             : 
    1688             :     /*
    1689             :      * Generate a targetlist as though expanding "*"
    1690             :      */
    1691             :     Assert(pstate->p_next_resno == 1);
    1692        8450 :     qry->targetList = expandNSItemAttrs(pstate, nsitem, 0, true, -1);
    1693             : 
    1694             :     /*
    1695             :      * The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE to a
    1696             :      * VALUES, so cope.
    1697             :      */
    1698        8450 :     qry->sortClause = transformSortClause(pstate,
    1699             :                                           stmt->sortClause,
    1700             :                                           &qry->targetList,
    1701             :                                           EXPR_KIND_ORDER_BY,
    1702             :                                           false /* allow SQL92 rules */ );
    1703             : 
    1704        8450 :     qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
    1705             :                                             EXPR_KIND_OFFSET, "OFFSET",
    1706             :                                             stmt->limitOption);
    1707        8450 :     qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
    1708             :                                            EXPR_KIND_LIMIT, "LIMIT",
    1709             :                                            stmt->limitOption);
    1710        8450 :     qry->limitOption = stmt->limitOption;
    1711             : 
    1712        8450 :     if (stmt->lockingClause)
    1713           0 :         ereport(ERROR,
    1714             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1715             :         /*------
    1716             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    1717             :                  errmsg("%s cannot be applied to VALUES",
    1718             :                         LCS_asString(((LockingClause *)
    1719             :                                       linitial(stmt->lockingClause))->strength))));
    1720             : 
    1721        8450 :     qry->rtable = pstate->p_rtable;
    1722        8450 :     qry->rteperminfos = pstate->p_rteperminfos;
    1723        8450 :     qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
    1724             : 
    1725        8450 :     qry->hasSubLinks = pstate->p_hasSubLinks;
    1726             : 
    1727        8450 :     assign_query_collations(pstate, qry);
    1728             : 
    1729        8450 :     return qry;
    1730             : }
    1731             : 
    1732             : /*
    1733             :  * transformSetOperationStmt -
    1734             :  *    transforms a set-operations tree
    1735             :  *
    1736             :  * A set-operation tree is just a SELECT, but with UNION/INTERSECT/EXCEPT
    1737             :  * structure to it.  We must transform each leaf SELECT and build up a top-
    1738             :  * level Query that contains the leaf SELECTs as subqueries in its rangetable.
    1739             :  * The tree of set operations is converted into the setOperations field of
    1740             :  * the top-level Query.
    1741             :  */
    1742             : static Query *
    1743       12592 : transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
    1744             : {
    1745       12592 :     Query      *qry = makeNode(Query);
    1746             :     SelectStmt *leftmostSelect;
    1747             :     int         leftmostRTI;
    1748             :     Query      *leftmostQuery;
    1749             :     SetOperationStmt *sostmt;
    1750             :     List       *sortClause;
    1751             :     Node       *limitOffset;
    1752             :     Node       *limitCount;
    1753             :     List       *lockingClause;
    1754             :     WithClause *withClause;
    1755             :     Node       *node;
    1756             :     ListCell   *left_tlist,
    1757             :                *lct,
    1758             :                *lcm,
    1759             :                *lcc,
    1760             :                *l;
    1761             :     List       *targetvars,
    1762             :                *targetnames,
    1763             :                *sv_namespace;
    1764             :     int         sv_rtable_length;
    1765             :     ParseNamespaceItem *jnsitem;
    1766             :     ParseNamespaceColumn *sortnscolumns;
    1767             :     int         sortcolindex;
    1768             :     int         tllen;
    1769             : 
    1770       12592 :     qry->commandType = CMD_SELECT;
    1771             : 
    1772             :     /*
    1773             :      * Find leftmost leaf SelectStmt.  We currently only need to do this in
    1774             :      * order to deliver a suitable error message if there's an INTO clause
    1775             :      * there, implying the set-op tree is in a context that doesn't allow
    1776             :      * INTO.  (transformSetOperationTree would throw error anyway, but it
    1777             :      * seems worth the trouble to throw a different error for non-leftmost
    1778             :      * INTO, so we produce that error in transformSetOperationTree.)
    1779             :      */
    1780       12592 :     leftmostSelect = stmt->larg;
    1781       19168 :     while (leftmostSelect && leftmostSelect->op != SETOP_NONE)
    1782        6576 :         leftmostSelect = leftmostSelect->larg;
    1783             :     Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
    1784             :            leftmostSelect->larg == NULL);
    1785       12592 :     if (leftmostSelect->intoClause)
    1786           0 :         ereport(ERROR,
    1787             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    1788             :                  errmsg("SELECT ... INTO is not allowed here"),
    1789             :                  parser_errposition(pstate,
    1790             :                                     exprLocation((Node *) leftmostSelect->intoClause))));
    1791             : 
    1792             :     /*
    1793             :      * We need to extract ORDER BY and other top-level clauses here and not
    1794             :      * let transformSetOperationTree() see them --- else it'll just recurse
    1795             :      * right back here!
    1796             :      */
    1797       12592 :     sortClause = stmt->sortClause;
    1798       12592 :     limitOffset = stmt->limitOffset;
    1799       12592 :     limitCount = stmt->limitCount;
    1800       12592 :     lockingClause = stmt->lockingClause;
    1801       12592 :     withClause = stmt->withClause;
    1802             : 
    1803       12592 :     stmt->sortClause = NIL;
    1804       12592 :     stmt->limitOffset = NULL;
    1805       12592 :     stmt->limitCount = NULL;
    1806       12592 :     stmt->lockingClause = NIL;
    1807       12592 :     stmt->withClause = NULL;
    1808             : 
    1809             :     /* We don't support FOR UPDATE/SHARE with set ops at the moment. */
    1810       12592 :     if (lockingClause)
    1811           6 :         ereport(ERROR,
    1812             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1813             :         /*------
    1814             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    1815             :                  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
    1816             :                         LCS_asString(((LockingClause *)
    1817             :                                       linitial(lockingClause))->strength))));
    1818             : 
    1819             :     /* Process the WITH clause independently of all else */
    1820       12586 :     if (withClause)
    1821             :     {
    1822         236 :         qry->hasRecursive = withClause->recursive;
    1823         236 :         qry->cteList = transformWithClause(pstate, withClause);
    1824         236 :         qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
    1825             :     }
    1826             : 
    1827             :     /*
    1828             :      * Recursively transform the components of the tree.
    1829             :      */
    1830       12586 :     sostmt = castNode(SetOperationStmt,
    1831             :                       transformSetOperationTree(pstate, stmt, true, NULL));
    1832             :     Assert(sostmt);
    1833       12514 :     qry->setOperations = (Node *) sostmt;
    1834             : 
    1835             :     /*
    1836             :      * Re-find leftmost SELECT (now it's a sub-query in rangetable)
    1837             :      */
    1838       12514 :     node = sostmt->larg;
    1839       19072 :     while (node && IsA(node, SetOperationStmt))
    1840        6558 :         node = ((SetOperationStmt *) node)->larg;
    1841             :     Assert(node && IsA(node, RangeTblRef));
    1842       12514 :     leftmostRTI = ((RangeTblRef *) node)->rtindex;
    1843       12514 :     leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
    1844             :     Assert(leftmostQuery != NULL);
    1845             : 
    1846             :     /*
    1847             :      * Generate dummy targetlist for outer query using column names of
    1848             :      * leftmost select and common datatypes/collations of topmost set
    1849             :      * operation.  Also make lists of the dummy vars and their names for use
    1850             :      * in parsing ORDER BY.
    1851             :      *
    1852             :      * Note: we use leftmostRTI as the varno of the dummy variables. It
    1853             :      * shouldn't matter too much which RT index they have, as long as they
    1854             :      * have one that corresponds to a real RT entry; else funny things may
    1855             :      * happen when the tree is mashed by rule rewriting.
    1856             :      */
    1857       12514 :     qry->targetList = NIL;
    1858       12514 :     targetvars = NIL;
    1859       12514 :     targetnames = NIL;
    1860             :     sortnscolumns = (ParseNamespaceColumn *)
    1861       12514 :         palloc0(list_length(sostmt->colTypes) * sizeof(ParseNamespaceColumn));
    1862       12514 :     sortcolindex = 0;
    1863             : 
    1864       43674 :     forfour(lct, sostmt->colTypes,
    1865             :             lcm, sostmt->colTypmods,
    1866             :             lcc, sostmt->colCollations,
    1867             :             left_tlist, leftmostQuery->targetList)
    1868             :     {
    1869       31160 :         Oid         colType = lfirst_oid(lct);
    1870       31160 :         int32       colTypmod = lfirst_int(lcm);
    1871       31160 :         Oid         colCollation = lfirst_oid(lcc);
    1872       31160 :         TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
    1873             :         char       *colName;
    1874             :         TargetEntry *tle;
    1875             :         Var        *var;
    1876             : 
    1877             :         Assert(!lefttle->resjunk);
    1878       31160 :         colName = pstrdup(lefttle->resname);
    1879       31160 :         var = makeVar(leftmostRTI,
    1880       31160 :                       lefttle->resno,
    1881             :                       colType,
    1882             :                       colTypmod,
    1883             :                       colCollation,
    1884             :                       0);
    1885       31160 :         var->location = exprLocation((Node *) lefttle->expr);
    1886       31160 :         tle = makeTargetEntry((Expr *) var,
    1887       31160 :                               (AttrNumber) pstate->p_next_resno++,
    1888             :                               colName,
    1889             :                               false);
    1890       31160 :         qry->targetList = lappend(qry->targetList, tle);
    1891       31160 :         targetvars = lappend(targetvars, var);
    1892       31160 :         targetnames = lappend(targetnames, makeString(colName));
    1893       31160 :         sortnscolumns[sortcolindex].p_varno = leftmostRTI;
    1894       31160 :         sortnscolumns[sortcolindex].p_varattno = lefttle->resno;
    1895       31160 :         sortnscolumns[sortcolindex].p_vartype = colType;
    1896       31160 :         sortnscolumns[sortcolindex].p_vartypmod = colTypmod;
    1897       31160 :         sortnscolumns[sortcolindex].p_varcollid = colCollation;
    1898       31160 :         sortnscolumns[sortcolindex].p_varnosyn = leftmostRTI;
    1899       31160 :         sortnscolumns[sortcolindex].p_varattnosyn = lefttle->resno;
    1900       31160 :         sortcolindex++;
    1901             :     }
    1902             : 
    1903             :     /*
    1904             :      * As a first step towards supporting sort clauses that are expressions
    1905             :      * using the output columns, generate a namespace entry that makes the
    1906             :      * output columns visible.  A Join RTE node is handy for this, since we
    1907             :      * can easily control the Vars generated upon matches.
    1908             :      *
    1909             :      * Note: we don't yet do anything useful with such cases, but at least
    1910             :      * "ORDER BY upper(foo)" will draw the right error message rather than
    1911             :      * "foo not found".
    1912             :      */
    1913       12514 :     sv_rtable_length = list_length(pstate->p_rtable);
    1914             : 
    1915       12514 :     jnsitem = addRangeTableEntryForJoin(pstate,
    1916             :                                         targetnames,
    1917             :                                         sortnscolumns,
    1918             :                                         JOIN_INNER,
    1919             :                                         0,
    1920             :                                         targetvars,
    1921             :                                         NIL,
    1922             :                                         NIL,
    1923             :                                         NULL,
    1924             :                                         NULL,
    1925             :                                         false);
    1926             : 
    1927       12514 :     sv_namespace = pstate->p_namespace;
    1928       12514 :     pstate->p_namespace = NIL;
    1929             : 
    1930             :     /* add jnsitem to column namespace only */
    1931       12514 :     addNSItemToQuery(pstate, jnsitem, false, false, true);
    1932             : 
    1933             :     /*
    1934             :      * For now, we don't support resjunk sort clauses on the output of a
    1935             :      * setOperation tree --- you can only use the SQL92-spec options of
    1936             :      * selecting an output column by name or number.  Enforce by checking that
    1937             :      * transformSortClause doesn't add any items to tlist.  Note, if changing
    1938             :      * this, add_setop_child_rel_equivalences() will need to be updated.
    1939             :      */
    1940       12514 :     tllen = list_length(qry->targetList);
    1941             : 
    1942       12514 :     qry->sortClause = transformSortClause(pstate,
    1943             :                                           sortClause,
    1944             :                                           &qry->targetList,
    1945             :                                           EXPR_KIND_ORDER_BY,
    1946             :                                           false /* allow SQL92 rules */ );
    1947             : 
    1948             :     /* restore namespace, remove join RTE from rtable */
    1949       12508 :     pstate->p_namespace = sv_namespace;
    1950       12508 :     pstate->p_rtable = list_truncate(pstate->p_rtable, sv_rtable_length);
    1951             : 
    1952       12508 :     if (tllen != list_length(qry->targetList))
    1953           0 :         ereport(ERROR,
    1954             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1955             :                  errmsg("invalid UNION/INTERSECT/EXCEPT ORDER BY clause"),
    1956             :                  errdetail("Only result column names can be used, not expressions or functions."),
    1957             :                  errhint("Add the expression/function to every SELECT, or move the UNION into a FROM clause."),
    1958             :                  parser_errposition(pstate,
    1959             :                                     exprLocation(list_nth(qry->targetList, tllen)))));
    1960             : 
    1961       12508 :     qry->limitOffset = transformLimitClause(pstate, limitOffset,
    1962             :                                             EXPR_KIND_OFFSET, "OFFSET",
    1963             :                                             stmt->limitOption);
    1964       12508 :     qry->limitCount = transformLimitClause(pstate, limitCount,
    1965             :                                            EXPR_KIND_LIMIT, "LIMIT",
    1966             :                                            stmt->limitOption);
    1967       12508 :     qry->limitOption = stmt->limitOption;
    1968             : 
    1969       12508 :     qry->rtable = pstate->p_rtable;
    1970       12508 :     qry->rteperminfos = pstate->p_rteperminfos;
    1971       12508 :     qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
    1972             : 
    1973       12508 :     qry->hasSubLinks = pstate->p_hasSubLinks;
    1974       12508 :     qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
    1975       12508 :     qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
    1976       12508 :     qry->hasAggs = pstate->p_hasAggs;
    1977             : 
    1978       12508 :     foreach(l, lockingClause)
    1979             :     {
    1980           0 :         transformLockingClause(pstate, qry,
    1981           0 :                                (LockingClause *) lfirst(l), false);
    1982             :     }
    1983             : 
    1984       12508 :     assign_query_collations(pstate, qry);
    1985             : 
    1986             :     /* this must be done after collations, for reliable comparison of exprs */
    1987       12508 :     if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
    1988           0 :         parseCheckAggregates(pstate, qry);
    1989             : 
    1990       12508 :     return qry;
    1991             : }
    1992             : 
    1993             : /*
    1994             :  * Make a SortGroupClause node for a SetOperationStmt's groupClauses
    1995             :  *
    1996             :  * If require_hash is true, the caller is indicating that they need hash
    1997             :  * support or they will fail.  So look extra hard for hash support.
    1998             :  */
    1999             : SortGroupClause *
    2000       26930 : makeSortGroupClauseForSetOp(Oid rescoltype, bool require_hash)
    2001             : {
    2002       26930 :     SortGroupClause *grpcl = makeNode(SortGroupClause);
    2003             :     Oid         sortop;
    2004             :     Oid         eqop;
    2005             :     bool        hashable;
    2006             : 
    2007             :     /* determine the eqop and optional sortop */
    2008       26930 :     get_sort_group_operators(rescoltype,
    2009             :                              false, true, false,
    2010             :                              &sortop, &eqop, NULL,
    2011             :                              &hashable);
    2012             : 
    2013             :     /*
    2014             :      * The type cache doesn't believe that record is hashable (see
    2015             :      * cache_record_field_properties()), but if the caller really needs hash
    2016             :      * support, we can assume it does.  Worst case, if any components of the
    2017             :      * record don't support hashing, we will fail at execution.
    2018             :      */
    2019       26930 :     if (require_hash && (rescoltype == RECORDOID || rescoltype == RECORDARRAYOID))
    2020          24 :         hashable = true;
    2021             : 
    2022             :     /* we don't have a tlist yet, so can't assign sortgrouprefs */
    2023       26930 :     grpcl->tleSortGroupRef = 0;
    2024       26930 :     grpcl->eqop = eqop;
    2025       26930 :     grpcl->sortop = sortop;
    2026       26930 :     grpcl->reverse_sort = false; /* Sort-op is "less than", or InvalidOid */
    2027       26930 :     grpcl->nulls_first = false; /* OK with or without sortop */
    2028       26930 :     grpcl->hashable = hashable;
    2029             : 
    2030       26930 :     return grpcl;
    2031             : }
    2032             : 
    2033             : /*
    2034             :  * transformSetOperationTree
    2035             :  *      Recursively transform leaves and internal nodes of a set-op tree
    2036             :  *
    2037             :  * In addition to returning the transformed node, if targetlist isn't NULL
    2038             :  * then we return a list of its non-resjunk TargetEntry nodes.  For a leaf
    2039             :  * set-op node these are the actual targetlist entries; otherwise they are
    2040             :  * dummy entries created to carry the type, typmod, collation, and location
    2041             :  * (for error messages) of each output column of the set-op node.  This info
    2042             :  * is needed only during the internal recursion of this function, so outside
    2043             :  * callers pass NULL for targetlist.  Note: the reason for passing the
    2044             :  * actual targetlist entries of a leaf node is so that upper levels can
    2045             :  * replace UNKNOWN Consts with properly-coerced constants.
    2046             :  */
    2047             : static Node *
    2048       51012 : transformSetOperationTree(ParseState *pstate, SelectStmt *stmt,
    2049             :                           bool isTopLevel, List **targetlist)
    2050             : {
    2051             :     bool        isLeaf;
    2052             : 
    2053             :     Assert(stmt && IsA(stmt, SelectStmt));
    2054             : 
    2055             :     /* Guard against stack overflow due to overly complex set-expressions */
    2056       51012 :     check_stack_depth();
    2057             : 
    2058             :     /*
    2059             :      * Validity-check both leaf and internal SELECTs for disallowed ops.
    2060             :      */
    2061       51012 :     if (stmt->intoClause)
    2062           0 :         ereport(ERROR,
    2063             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    2064             :                  errmsg("INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"),
    2065             :                  parser_errposition(pstate,
    2066             :                                     exprLocation((Node *) stmt->intoClause))));
    2067             : 
    2068             :     /* We don't support FOR UPDATE/SHARE with set ops at the moment. */
    2069       51012 :     if (stmt->lockingClause)
    2070           0 :         ereport(ERROR,
    2071             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2072             :         /*------
    2073             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    2074             :                  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
    2075             :                         LCS_asString(((LockingClause *)
    2076             :                                       linitial(stmt->lockingClause))->strength))));
    2077             : 
    2078             :     /*
    2079             :      * If an internal node of a set-op tree has ORDER BY, LIMIT, FOR UPDATE,
    2080             :      * or WITH clauses attached, we need to treat it like a leaf node to
    2081             :      * generate an independent sub-Query tree.  Otherwise, it can be
    2082             :      * represented by a SetOperationStmt node underneath the parent Query.
    2083             :      */
    2084       51012 :     if (stmt->op == SETOP_NONE)
    2085             :     {
    2086             :         Assert(stmt->larg == NULL && stmt->rarg == NULL);
    2087       31736 :         isLeaf = true;
    2088             :     }
    2089             :     else
    2090             :     {
    2091             :         Assert(stmt->larg != NULL && stmt->rarg != NULL);
    2092       19276 :         if (stmt->sortClause || stmt->limitOffset || stmt->limitCount ||
    2093       19252 :             stmt->lockingClause || stmt->withClause)
    2094          60 :             isLeaf = true;
    2095             :         else
    2096       19216 :             isLeaf = false;
    2097             :     }
    2098             : 
    2099       51012 :     if (isLeaf)
    2100             :     {
    2101             :         /* Process leaf SELECT */
    2102             :         Query      *selectQuery;
    2103             :         char        selectName[32];
    2104             :         ParseNamespaceItem *nsitem;
    2105             :         RangeTblRef *rtr;
    2106             :         ListCell   *tl;
    2107             : 
    2108             :         /*
    2109             :          * Transform SelectStmt into a Query.
    2110             :          *
    2111             :          * This works the same as SELECT transformation normally would, except
    2112             :          * that we prevent resolving unknown-type outputs as TEXT.  This does
    2113             :          * not change the subquery's semantics since if the column type
    2114             :          * matters semantically, it would have been resolved to something else
    2115             :          * anyway.  Doing this lets us resolve such outputs using
    2116             :          * select_common_type(), below.
    2117             :          *
    2118             :          * Note: previously transformed sub-queries don't affect the parsing
    2119             :          * of this sub-query, because they are not in the toplevel pstate's
    2120             :          * namespace list.
    2121             :          */
    2122       31796 :         selectQuery = parse_sub_analyze((Node *) stmt, pstate,
    2123             :                                         NULL, false, false);
    2124             : 
    2125             :         /*
    2126             :          * Check for bogus references to Vars on the current query level (but
    2127             :          * upper-level references are okay). Normally this can't happen
    2128             :          * because the namespace will be empty, but it could happen if we are
    2129             :          * inside a rule.
    2130             :          */
    2131       31766 :         if (pstate->p_namespace)
    2132             :         {
    2133           0 :             if (contain_vars_of_level((Node *) selectQuery, 1))
    2134           0 :                 ereport(ERROR,
    2135             :                         (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    2136             :                          errmsg("UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level"),
    2137             :                          parser_errposition(pstate,
    2138             :                                             locate_var_of_level((Node *) selectQuery, 1))));
    2139             :         }
    2140             : 
    2141             :         /*
    2142             :          * Extract a list of the non-junk TLEs for upper-level processing.
    2143             :          */
    2144       31766 :         if (targetlist)
    2145             :         {
    2146       31766 :             *targetlist = NIL;
    2147      123738 :             foreach(tl, selectQuery->targetList)
    2148             :             {
    2149       91972 :                 TargetEntry *tle = (TargetEntry *) lfirst(tl);
    2150             : 
    2151       91972 :                 if (!tle->resjunk)
    2152       91960 :                     *targetlist = lappend(*targetlist, tle);
    2153             :             }
    2154             :         }
    2155             : 
    2156             :         /*
    2157             :          * Make the leaf query be a subquery in the top-level rangetable.
    2158             :          */
    2159       31766 :         snprintf(selectName, sizeof(selectName), "*SELECT* %d",
    2160       31766 :                  list_length(pstate->p_rtable) + 1);
    2161       31766 :         nsitem = addRangeTableEntryForSubquery(pstate,
    2162             :                                                selectQuery,
    2163             :                                                makeAlias(selectName, NIL),
    2164             :                                                false,
    2165             :                                                false);
    2166             : 
    2167             :         /*
    2168             :          * Return a RangeTblRef to replace the SelectStmt in the set-op tree.
    2169             :          */
    2170       31766 :         rtr = makeNode(RangeTblRef);
    2171       31766 :         rtr->rtindex = nsitem->p_rtindex;
    2172       31766 :         return (Node *) rtr;
    2173             :     }
    2174             :     else
    2175             :     {
    2176             :         /* Process an internal node (set operation node) */
    2177       19216 :         SetOperationStmt *op = makeNode(SetOperationStmt);
    2178             :         List       *ltargetlist;
    2179             :         List       *rtargetlist;
    2180             :         ListCell   *ltl;
    2181             :         ListCell   *rtl;
    2182             :         const char *context;
    2183       20506 :         bool        recursive = (pstate->p_parent_cte &&
    2184        1290 :                                  pstate->p_parent_cte->cterecursive);
    2185             : 
    2186       19908 :         context = (stmt->op == SETOP_UNION ? "UNION" :
    2187         692 :                    (stmt->op == SETOP_INTERSECT ? "INTERSECT" :
    2188             :                     "EXCEPT"));
    2189             : 
    2190       19216 :         op->op = stmt->op;
    2191       19216 :         op->all = stmt->all;
    2192             : 
    2193             :         /*
    2194             :          * Recursively transform the left child node.
    2195             :          */
    2196       19216 :         op->larg = transformSetOperationTree(pstate, stmt->larg,
    2197             :                                              false,
    2198             :                                              &ltargetlist);
    2199             : 
    2200             :         /*
    2201             :          * If we are processing a recursive union query, now is the time to
    2202             :          * examine the non-recursive term's output columns and mark the
    2203             :          * containing CTE as having those result columns.  We should do this
    2204             :          * only at the topmost setop of the CTE, of course.
    2205             :          */
    2206       19210 :         if (isTopLevel && recursive)
    2207        1146 :             determineRecursiveColTypes(pstate, op->larg, ltargetlist);
    2208             : 
    2209             :         /*
    2210             :          * Recursively transform the right child node.
    2211             :          */
    2212       19210 :         op->rarg = transformSetOperationTree(pstate, stmt->rarg,
    2213             :                                              false,
    2214             :                                              &rtargetlist);
    2215             : 
    2216             :         /*
    2217             :          * Verify that the two children have the same number of non-junk
    2218             :          * columns, and determine the types of the merged output columns.
    2219             :          */
    2220       19186 :         if (list_length(ltargetlist) != list_length(rtargetlist))
    2221           0 :             ereport(ERROR,
    2222             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    2223             :                      errmsg("each %s query must have the same number of columns",
    2224             :                             context),
    2225             :                      parser_errposition(pstate,
    2226             :                                         exprLocation((Node *) rtargetlist))));
    2227             : 
    2228       19186 :         if (targetlist)
    2229        6630 :             *targetlist = NIL;
    2230       19186 :         op->colTypes = NIL;
    2231       19186 :         op->colTypmods = NIL;
    2232       19186 :         op->colCollations = NIL;
    2233       19186 :         op->groupClauses = NIL;
    2234       79842 :         forboth(ltl, ltargetlist, rtl, rtargetlist)
    2235             :         {
    2236       60698 :             TargetEntry *ltle = (TargetEntry *) lfirst(ltl);
    2237       60698 :             TargetEntry *rtle = (TargetEntry *) lfirst(rtl);
    2238       60698 :             Node       *lcolnode = (Node *) ltle->expr;
    2239       60698 :             Node       *rcolnode = (Node *) rtle->expr;
    2240       60698 :             Oid         lcoltype = exprType(lcolnode);
    2241       60698 :             Oid         rcoltype = exprType(rcolnode);
    2242             :             Node       *bestexpr;
    2243             :             int         bestlocation;
    2244             :             Oid         rescoltype;
    2245             :             int32       rescoltypmod;
    2246             :             Oid         rescolcoll;
    2247             : 
    2248             :             /* select common type, same as CASE et al */
    2249       60698 :             rescoltype = select_common_type(pstate,
    2250       60698 :                                             list_make2(lcolnode, rcolnode),
    2251             :                                             context,
    2252             :                                             &bestexpr);
    2253       60698 :             bestlocation = exprLocation(bestexpr);
    2254             : 
    2255             :             /*
    2256             :              * Verify the coercions are actually possible.  If not, we'd fail
    2257             :              * later anyway, but we want to fail now while we have sufficient
    2258             :              * context to produce an error cursor position.
    2259             :              *
    2260             :              * For all non-UNKNOWN-type cases, we verify coercibility but we
    2261             :              * don't modify the child's expression, for fear of changing the
    2262             :              * child query's semantics.
    2263             :              *
    2264             :              * If a child expression is an UNKNOWN-type Const or Param, we
    2265             :              * want to replace it with the coerced expression.  This can only
    2266             :              * happen when the child is a leaf set-op node.  It's safe to
    2267             :              * replace the expression because if the child query's semantics
    2268             :              * depended on the type of this output column, it'd have already
    2269             :              * coerced the UNKNOWN to something else.  We want to do this
    2270             :              * because (a) we want to verify that a Const is valid for the
    2271             :              * target type, or resolve the actual type of an UNKNOWN Param,
    2272             :              * and (b) we want to avoid unnecessary discrepancies between the
    2273             :              * output type of the child query and the resolved target type.
    2274             :              * Such a discrepancy would disable optimization in the planner.
    2275             :              *
    2276             :              * If it's some other UNKNOWN-type node, eg a Var, we do nothing
    2277             :              * (knowing that coerce_to_common_type would fail).  The planner
    2278             :              * is sometimes able to fold an UNKNOWN Var to a constant before
    2279             :              * it has to coerce the type, so failing now would just break
    2280             :              * cases that might work.
    2281             :              */
    2282       60698 :             if (lcoltype != UNKNOWNOID)
    2283       54436 :                 lcolnode = coerce_to_common_type(pstate, lcolnode,
    2284             :                                                  rescoltype, context);
    2285        6262 :             else if (IsA(lcolnode, Const) ||
    2286           0 :                      IsA(lcolnode, Param))
    2287             :             {
    2288        6262 :                 lcolnode = coerce_to_common_type(pstate, lcolnode,
    2289             :                                                  rescoltype, context);
    2290        6262 :                 ltle->expr = (Expr *) lcolnode;
    2291             :             }
    2292             : 
    2293       60698 :             if (rcoltype != UNKNOWNOID)
    2294       53600 :                 rcolnode = coerce_to_common_type(pstate, rcolnode,
    2295             :                                                  rescoltype, context);
    2296        7098 :             else if (IsA(rcolnode, Const) ||
    2297           0 :                      IsA(rcolnode, Param))
    2298             :             {
    2299        7098 :                 rcolnode = coerce_to_common_type(pstate, rcolnode,
    2300             :                                                  rescoltype, context);
    2301        7092 :                 rtle->expr = (Expr *) rcolnode;
    2302             :             }
    2303             : 
    2304       60692 :             rescoltypmod = select_common_typmod(pstate,
    2305       60692 :                                                 list_make2(lcolnode, rcolnode),
    2306             :                                                 rescoltype);
    2307             : 
    2308             :             /*
    2309             :              * Select common collation.  A common collation is required for
    2310             :              * all set operators except UNION ALL; see SQL:2008 7.13 <query
    2311             :              * expression> Syntax Rule 15c.  (If we fail to identify a common
    2312             :              * collation for a UNION ALL column, the colCollations element
    2313             :              * will be set to InvalidOid, which may result in a runtime error
    2314             :              * if something at a higher query level wants to use the column's
    2315             :              * collation.)
    2316             :              */
    2317       60692 :             rescolcoll = select_common_collation(pstate,
    2318       60692 :                                                  list_make2(lcolnode, rcolnode),
    2319       60692 :                                                  (op->op == SETOP_UNION && op->all));
    2320             : 
    2321             :             /* emit results */
    2322       60656 :             op->colTypes = lappend_oid(op->colTypes, rescoltype);
    2323       60656 :             op->colTypmods = lappend_int(op->colTypmods, rescoltypmod);
    2324       60656 :             op->colCollations = lappend_oid(op->colCollations, rescolcoll);
    2325             : 
    2326             :             /*
    2327             :              * For all cases except UNION ALL, identify the grouping operators
    2328             :              * (and, if available, sorting operators) that will be used to
    2329             :              * eliminate duplicates.
    2330             :              */
    2331       60656 :             if (op->op != SETOP_UNION || !op->all)
    2332             :             {
    2333             :                 ParseCallbackState pcbstate;
    2334             : 
    2335       26906 :                 setup_parser_errposition_callback(&pcbstate, pstate,
    2336             :                                                   bestlocation);
    2337             : 
    2338             :                 /*
    2339             :                  * If it's a recursive union, we need to require hashing
    2340             :                  * support.
    2341             :                  */
    2342       26906 :                 op->groupClauses = lappend(op->groupClauses,
    2343       26906 :                                            makeSortGroupClauseForSetOp(rescoltype, recursive));
    2344             : 
    2345       26906 :                 cancel_parser_errposition_callback(&pcbstate);
    2346             :             }
    2347             : 
    2348             :             /*
    2349             :              * Construct a dummy tlist entry to return.  We use a SetToDefault
    2350             :              * node for the expression, since it carries exactly the fields
    2351             :              * needed, but any other expression node type would do as well.
    2352             :              */
    2353       60656 :             if (targetlist)
    2354             :             {
    2355       29460 :                 SetToDefault *rescolnode = makeNode(SetToDefault);
    2356             :                 TargetEntry *restle;
    2357             : 
    2358       29460 :                 rescolnode->typeId = rescoltype;
    2359       29460 :                 rescolnode->typeMod = rescoltypmod;
    2360       29460 :                 rescolnode->collation = rescolcoll;
    2361       29460 :                 rescolnode->location = bestlocation;
    2362       29460 :                 restle = makeTargetEntry((Expr *) rescolnode,
    2363             :                                          0, /* no need to set resno */
    2364             :                                          NULL,
    2365             :                                          false);
    2366       29460 :                 *targetlist = lappend(*targetlist, restle);
    2367             :             }
    2368             :         }
    2369             : 
    2370       19144 :         return (Node *) op;
    2371             :     }
    2372             : }
    2373             : 
    2374             : /*
    2375             :  * Process the outputs of the non-recursive term of a recursive union
    2376             :  * to set up the parent CTE's columns
    2377             :  */
    2378             : static void
    2379        1146 : determineRecursiveColTypes(ParseState *pstate, Node *larg, List *nrtargetlist)
    2380             : {
    2381             :     Node       *node;
    2382             :     int         leftmostRTI;
    2383             :     Query      *leftmostQuery;
    2384             :     List       *targetList;
    2385             :     ListCell   *left_tlist;
    2386             :     ListCell   *nrtl;
    2387             :     int         next_resno;
    2388             : 
    2389             :     /*
    2390             :      * Find leftmost leaf SELECT
    2391             :      */
    2392        1146 :     node = larg;
    2393        1152 :     while (node && IsA(node, SetOperationStmt))
    2394           6 :         node = ((SetOperationStmt *) node)->larg;
    2395             :     Assert(node && IsA(node, RangeTblRef));
    2396        1146 :     leftmostRTI = ((RangeTblRef *) node)->rtindex;
    2397        1146 :     leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
    2398             :     Assert(leftmostQuery != NULL);
    2399             : 
    2400             :     /*
    2401             :      * Generate dummy targetlist using column names of leftmost select and
    2402             :      * dummy result expressions of the non-recursive term.
    2403             :      */
    2404        1146 :     targetList = NIL;
    2405        1146 :     next_resno = 1;
    2406             : 
    2407        3674 :     forboth(nrtl, nrtargetlist, left_tlist, leftmostQuery->targetList)
    2408             :     {
    2409        2528 :         TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
    2410        2528 :         TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
    2411             :         char       *colName;
    2412             :         TargetEntry *tle;
    2413             : 
    2414             :         Assert(!lefttle->resjunk);
    2415        2528 :         colName = pstrdup(lefttle->resname);
    2416        2528 :         tle = makeTargetEntry(nrtle->expr,
    2417        2528 :                               next_resno++,
    2418             :                               colName,
    2419             :                               false);
    2420        2528 :         targetList = lappend(targetList, tle);
    2421             :     }
    2422             : 
    2423             :     /* Now build CTE's output column info using dummy targetlist */
    2424        1146 :     analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
    2425        1146 : }
    2426             : 
    2427             : 
    2428             : /*
    2429             :  * transformReturnStmt -
    2430             :  *    transforms a return statement
    2431             :  */
    2432             : static Query *
    2433        4870 : transformReturnStmt(ParseState *pstate, ReturnStmt *stmt)
    2434             : {
    2435        4870 :     Query      *qry = makeNode(Query);
    2436             : 
    2437        4870 :     qry->commandType = CMD_SELECT;
    2438        4870 :     qry->isReturn = true;
    2439             : 
    2440        4870 :     qry->targetList = list_make1(makeTargetEntry((Expr *) transformExpr(pstate, stmt->returnval, EXPR_KIND_SELECT_TARGET),
    2441             :                                                  1, NULL, false));
    2442             : 
    2443        4864 :     if (pstate->p_resolve_unknowns)
    2444        4864 :         resolveTargetListUnknowns(pstate, qry->targetList);
    2445        4864 :     qry->rtable = pstate->p_rtable;
    2446        4864 :     qry->rteperminfos = pstate->p_rteperminfos;
    2447        4864 :     qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
    2448        4864 :     qry->hasSubLinks = pstate->p_hasSubLinks;
    2449        4864 :     qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
    2450        4864 :     qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
    2451        4864 :     qry->hasAggs = pstate->p_hasAggs;
    2452             : 
    2453        4864 :     assign_query_collations(pstate, qry);
    2454             : 
    2455        4864 :     return qry;
    2456             : }
    2457             : 
    2458             : 
    2459             : /*
    2460             :  * transformUpdateStmt -
    2461             :  *    transforms an update statement
    2462             :  */
    2463             : static Query *
    2464       13770 : transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
    2465             : {
    2466       13770 :     Query      *qry = makeNode(Query);
    2467             :     ParseNamespaceItem *nsitem;
    2468             :     Node       *qual;
    2469             : 
    2470       13770 :     qry->commandType = CMD_UPDATE;
    2471       13770 :     pstate->p_is_insert = false;
    2472             : 
    2473             :     /* process the WITH clause independently of all else */
    2474       13770 :     if (stmt->withClause)
    2475             :     {
    2476          70 :         qry->hasRecursive = stmt->withClause->recursive;
    2477          70 :         qry->cteList = transformWithClause(pstate, stmt->withClause);
    2478          70 :         qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
    2479             :     }
    2480             : 
    2481       27538 :     qry->resultRelation = setTargetTable(pstate, stmt->relation,
    2482       13770 :                                          stmt->relation->inh,
    2483             :                                          true,
    2484             :                                          ACL_UPDATE);
    2485       13768 :     nsitem = pstate->p_target_nsitem;
    2486             : 
    2487             :     /* subqueries in FROM cannot access the result relation */
    2488       13768 :     nsitem->p_lateral_only = true;
    2489       13768 :     nsitem->p_lateral_ok = false;
    2490             : 
    2491             :     /*
    2492             :      * the FROM clause is non-standard SQL syntax. We used to be able to do
    2493             :      * this with REPLACE in POSTQUEL so we keep the feature.
    2494             :      */
    2495       13768 :     transformFromClause(pstate, stmt->fromClause);
    2496             : 
    2497             :     /* remaining clauses can reference the result relation normally */
    2498       13744 :     nsitem->p_lateral_only = false;
    2499       13744 :     nsitem->p_lateral_ok = true;
    2500             : 
    2501       13744 :     qual = transformWhereClause(pstate, stmt->whereClause,
    2502             :                                 EXPR_KIND_WHERE, "WHERE");
    2503             : 
    2504       13732 :     transformReturningClause(pstate, qry, stmt->returningClause,
    2505             :                              EXPR_KIND_RETURNING);
    2506             : 
    2507             :     /*
    2508             :      * Now we are done with SELECT-like processing, and can get on with
    2509             :      * transforming the target list to match the UPDATE target columns.
    2510             :      */
    2511       13714 :     qry->targetList = transformUpdateTargetList(pstate, stmt->targetList);
    2512             : 
    2513       13666 :     qry->rtable = pstate->p_rtable;
    2514       13666 :     qry->rteperminfos = pstate->p_rteperminfos;
    2515       13666 :     qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
    2516             : 
    2517       13666 :     qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
    2518       13666 :     qry->hasSubLinks = pstate->p_hasSubLinks;
    2519             : 
    2520       13666 :     assign_query_collations(pstate, qry);
    2521             : 
    2522       13666 :     return qry;
    2523             : }
    2524             : 
    2525             : /*
    2526             :  * transformUpdateTargetList -
    2527             :  *  handle SET clause in UPDATE/MERGE/INSERT ... ON CONFLICT UPDATE
    2528             :  */
    2529             : List *
    2530       16452 : transformUpdateTargetList(ParseState *pstate, List *origTlist)
    2531             : {
    2532       16452 :     List       *tlist = NIL;
    2533             :     RTEPermissionInfo *target_perminfo;
    2534             :     ListCell   *orig_tl;
    2535             :     ListCell   *tl;
    2536             : 
    2537       16452 :     tlist = transformTargetList(pstate, origTlist,
    2538             :                                 EXPR_KIND_UPDATE_SOURCE);
    2539             : 
    2540             :     /* Prepare to assign non-conflicting resnos to resjunk attributes */
    2541       16404 :     if (pstate->p_next_resno <= RelationGetNumberOfAttributes(pstate->p_target_relation))
    2542       13828 :         pstate->p_next_resno = RelationGetNumberOfAttributes(pstate->p_target_relation) + 1;
    2543             : 
    2544             :     /* Prepare non-junk columns for assignment to target table */
    2545       16404 :     target_perminfo = pstate->p_target_nsitem->p_perminfo;
    2546       16404 :     orig_tl = list_head(origTlist);
    2547             : 
    2548       37074 :     foreach(tl, tlist)
    2549             :     {
    2550       20706 :         TargetEntry *tle = (TargetEntry *) lfirst(tl);
    2551             :         ResTarget  *origTarget;
    2552             :         int         attrno;
    2553             : 
    2554       20706 :         if (tle->resjunk)
    2555             :         {
    2556             :             /*
    2557             :              * Resjunk nodes need no additional processing, but be sure they
    2558             :              * have resnos that do not match any target columns; else rewriter
    2559             :              * or planner might get confused.  They don't need a resname
    2560             :              * either.
    2561             :              */
    2562         138 :             tle->resno = (AttrNumber) pstate->p_next_resno++;
    2563         138 :             tle->resname = NULL;
    2564         138 :             continue;
    2565             :         }
    2566       20568 :         if (orig_tl == NULL)
    2567           0 :             elog(ERROR, "UPDATE target count mismatch --- internal error");
    2568       20568 :         origTarget = lfirst_node(ResTarget, orig_tl);
    2569             : 
    2570       20568 :         attrno = attnameAttNum(pstate->p_target_relation,
    2571       20568 :                                origTarget->name, true);
    2572       20568 :         if (attrno == InvalidAttrNumber)
    2573          24 :             ereport(ERROR,
    2574             :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    2575             :                      errmsg("column \"%s\" of relation \"%s\" does not exist",
    2576             :                             origTarget->name,
    2577             :                             RelationGetRelationName(pstate->p_target_relation)),
    2578             :                      (origTarget->indirection != NIL &&
    2579             :                       strcmp(origTarget->name, pstate->p_target_nsitem->p_names->aliasname) == 0) ?
    2580             :                      errhint("SET target columns cannot be qualified with the relation name.") : 0,
    2581             :                      parser_errposition(pstate, origTarget->location)));
    2582             : 
    2583       20544 :         updateTargetListEntry(pstate, tle, origTarget->name,
    2584             :                               attrno,
    2585             :                               origTarget->indirection,
    2586             :                               origTarget->location);
    2587             : 
    2588             :         /* Mark the target column as requiring update permissions */
    2589       20532 :         target_perminfo->updatedCols = bms_add_member(target_perminfo->updatedCols,
    2590             :                                                       attrno - FirstLowInvalidHeapAttributeNumber);
    2591             : 
    2592       20532 :         orig_tl = lnext(origTlist, orig_tl);
    2593             :     }
    2594       16368 :     if (orig_tl != NULL)
    2595           0 :         elog(ERROR, "UPDATE target count mismatch --- internal error");
    2596             : 
    2597       16368 :     return tlist;
    2598             : }
    2599             : 
    2600             : /*
    2601             :  * addNSItemForReturning -
    2602             :  *  add a ParseNamespaceItem for the OLD or NEW alias in RETURNING.
    2603             :  */
    2604             : static void
    2605        6042 : addNSItemForReturning(ParseState *pstate, const char *aliasname,
    2606             :                       VarReturningType returning_type)
    2607             : {
    2608             :     List       *colnames;
    2609             :     int         numattrs;
    2610             :     ParseNamespaceColumn *nscolumns;
    2611             :     ParseNamespaceItem *nsitem;
    2612             : 
    2613             :     /* copy per-column data from the target relation */
    2614        6042 :     colnames = pstate->p_target_nsitem->p_rte->eref->colnames;
    2615        6042 :     numattrs = list_length(colnames);
    2616             : 
    2617             :     nscolumns = (ParseNamespaceColumn *)
    2618        6042 :         palloc(numattrs * sizeof(ParseNamespaceColumn));
    2619             : 
    2620        6042 :     memcpy(nscolumns, pstate->p_target_nsitem->p_nscolumns,
    2621             :            numattrs * sizeof(ParseNamespaceColumn));
    2622             : 
    2623             :     /* mark all columns as returning OLD/NEW */
    2624       24086 :     for (int i = 0; i < numattrs; i++)
    2625       18044 :         nscolumns[i].p_varreturningtype = returning_type;
    2626             : 
    2627             :     /* build the nsitem, copying most fields from the target relation */
    2628        6042 :     nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
    2629        6042 :     nsitem->p_names = makeAlias(aliasname, colnames);
    2630        6042 :     nsitem->p_rte = pstate->p_target_nsitem->p_rte;
    2631        6042 :     nsitem->p_rtindex = pstate->p_target_nsitem->p_rtindex;
    2632        6042 :     nsitem->p_perminfo = pstate->p_target_nsitem->p_perminfo;
    2633        6042 :     nsitem->p_nscolumns = nscolumns;
    2634        6042 :     nsitem->p_returning_type = returning_type;
    2635             : 
    2636             :     /* add it to the query namespace as a table-only item */
    2637        6042 :     addNSItemToQuery(pstate, nsitem, false, true, false);
    2638        6042 : }
    2639             : 
    2640             : /*
    2641             :  * transformReturningClause -
    2642             :  *  handle a RETURNING clause in INSERT/UPDATE/DELETE/MERGE
    2643             :  */
    2644             : void
    2645       21398 : transformReturningClause(ParseState *pstate, Query *qry,
    2646             :                          ReturningClause *returningClause,
    2647             :                          ParseExprKind exprKind)
    2648             : {
    2649       21398 :     int         save_nslen = list_length(pstate->p_namespace);
    2650             :     int         save_next_resno;
    2651             : 
    2652       21398 :     if (returningClause == NULL)
    2653       18308 :         return;                 /* nothing to do */
    2654             : 
    2655             :     /*
    2656             :      * Scan RETURNING WITH(...) options for OLD/NEW alias names.  Complain if
    2657             :      * there is any conflict with existing relations.
    2658             :      */
    2659        6252 :     foreach_node(ReturningOption, option, returningClause->options)
    2660             :     {
    2661         120 :         switch (option->option)
    2662             :         {
    2663          54 :             case RETURNING_OPTION_OLD:
    2664          54 :                 if (qry->returningOldAlias != NULL)
    2665           6 :                     ereport(ERROR,
    2666             :                             errcode(ERRCODE_SYNTAX_ERROR),
    2667             :                     /* translator: %s is OLD or NEW */
    2668             :                             errmsg("%s cannot be specified multiple times", "OLD"),
    2669             :                             parser_errposition(pstate, option->location));
    2670          48 :                 qry->returningOldAlias = option->value;
    2671          48 :                 break;
    2672             : 
    2673          66 :             case RETURNING_OPTION_NEW:
    2674          66 :                 if (qry->returningNewAlias != NULL)
    2675           6 :                     ereport(ERROR,
    2676             :                             errcode(ERRCODE_SYNTAX_ERROR),
    2677             :                     /* translator: %s is OLD or NEW */
    2678             :                             errmsg("%s cannot be specified multiple times", "NEW"),
    2679             :                             parser_errposition(pstate, option->location));
    2680          60 :                 qry->returningNewAlias = option->value;
    2681          60 :                 break;
    2682             : 
    2683           0 :             default:
    2684           0 :                 elog(ERROR, "unrecognized returning option: %d", option->option);
    2685             :         }
    2686             : 
    2687         108 :         if (refnameNamespaceItem(pstate, NULL, option->value, -1, NULL) != NULL)
    2688          12 :             ereport(ERROR,
    2689             :                     errcode(ERRCODE_DUPLICATE_ALIAS),
    2690             :                     errmsg("table name \"%s\" specified more than once",
    2691             :                            option->value),
    2692             :                     parser_errposition(pstate, option->location));
    2693             : 
    2694          96 :         addNSItemForReturning(pstate, option->value,
    2695          96 :                               option->option == RETURNING_OPTION_OLD ?
    2696             :                               VAR_RETURNING_OLD : VAR_RETURNING_NEW);
    2697             :     }
    2698             : 
    2699             :     /*
    2700             :      * If OLD/NEW alias names weren't explicitly specified, use "old"/"new"
    2701             :      * unless masked by existing relations.
    2702             :      */
    2703        6102 :     if (qry->returningOldAlias == NULL &&
    2704        3036 :         refnameNamespaceItem(pstate, NULL, "old", -1, NULL) == NULL)
    2705             :     {
    2706        2976 :         qry->returningOldAlias = "old";
    2707        2976 :         addNSItemForReturning(pstate, "old", VAR_RETURNING_OLD);
    2708             :     }
    2709        6096 :     if (qry->returningNewAlias == NULL &&
    2710        3030 :         refnameNamespaceItem(pstate, NULL, "new", -1, NULL) == NULL)
    2711             :     {
    2712        2970 :         qry->returningNewAlias = "new";
    2713        2970 :         addNSItemForReturning(pstate, "new", VAR_RETURNING_NEW);
    2714             :     }
    2715             : 
    2716             :     /*
    2717             :      * We need to assign resnos starting at one in the RETURNING list. Save
    2718             :      * and restore the main tlist's value of p_next_resno, just in case
    2719             :      * someone looks at it later (probably won't happen).
    2720             :      */
    2721        3066 :     save_next_resno = pstate->p_next_resno;
    2722        3066 :     pstate->p_next_resno = 1;
    2723             : 
    2724             :     /* transform RETURNING expressions identically to a SELECT targetlist */
    2725        3066 :     qry->returningList = transformTargetList(pstate,
    2726             :                                              returningClause->exprs,
    2727             :                                              exprKind);
    2728             : 
    2729             :     /*
    2730             :      * Complain if the nonempty tlist expanded to nothing (which is possible
    2731             :      * if it contains only a star-expansion of a zero-column table).  If we
    2732             :      * allow this, the parsed Query will look like it didn't have RETURNING,
    2733             :      * with results that would probably surprise the user.
    2734             :      */
    2735        3024 :     if (qry->returningList == NIL)
    2736           6 :         ereport(ERROR,
    2737             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    2738             :                  errmsg("RETURNING must have at least one column"),
    2739             :                  parser_errposition(pstate,
    2740             :                                     exprLocation(linitial(returningClause->exprs)))));
    2741             : 
    2742             :     /* mark column origins */
    2743        3018 :     markTargetListOrigins(pstate, qry->returningList);
    2744             : 
    2745             :     /* resolve any still-unresolved output columns as being type text */
    2746        3018 :     if (pstate->p_resolve_unknowns)
    2747        3018 :         resolveTargetListUnknowns(pstate, qry->returningList);
    2748             : 
    2749             :     /* restore state */
    2750        3018 :     pstate->p_namespace = list_truncate(pstate->p_namespace, save_nslen);
    2751        3018 :     pstate->p_next_resno = save_next_resno;
    2752             : }
    2753             : 
    2754             : 
    2755             : /*
    2756             :  * transformPLAssignStmt -
    2757             :  *    transform a PL/pgSQL assignment statement
    2758             :  *
    2759             :  * If there is no opt_indirection, the transformed statement looks like
    2760             :  * "SELECT a_expr ...", except the expression has been cast to the type of
    2761             :  * the target.  With indirection, it's still a SELECT, but the expression will
    2762             :  * incorporate FieldStore and/or assignment SubscriptingRef nodes to compute a
    2763             :  * new value for a container-type variable represented by the target.  The
    2764             :  * expression references the target as the container source.
    2765             :  */
    2766             : static Query *
    2767        5376 : transformPLAssignStmt(ParseState *pstate, PLAssignStmt *stmt)
    2768             : {
    2769        5376 :     Query      *qry = makeNode(Query);
    2770        5376 :     ColumnRef  *cref = makeNode(ColumnRef);
    2771        5376 :     List       *indirection = stmt->indirection;
    2772        5376 :     int         nnames = stmt->nnames;
    2773        5376 :     SelectStmt *sstmt = stmt->val;
    2774             :     Node       *target;
    2775             :     Oid         targettype;
    2776             :     int32       targettypmod;
    2777             :     Oid         targetcollation;
    2778             :     List       *tlist;
    2779             :     TargetEntry *tle;
    2780             :     Oid         type_id;
    2781             :     Node       *qual;
    2782             :     ListCell   *l;
    2783             : 
    2784             :     /*
    2785             :      * First, construct a ColumnRef for the target variable.  If the target
    2786             :      * has more than one dotted name, we have to pull the extra names out of
    2787             :      * the indirection list.
    2788             :      */
    2789        5376 :     cref->fields = list_make1(makeString(stmt->name));
    2790        5376 :     cref->location = stmt->location;
    2791        5376 :     if (nnames > 1)
    2792             :     {
    2793             :         /* avoid munging the raw parsetree */
    2794         378 :         indirection = list_copy(indirection);
    2795         770 :         while (--nnames > 0 && indirection != NIL)
    2796             :         {
    2797         392 :             Node       *ind = (Node *) linitial(indirection);
    2798             : 
    2799         392 :             if (!IsA(ind, String))
    2800           0 :                 elog(ERROR, "invalid name count in PLAssignStmt");
    2801         392 :             cref->fields = lappend(cref->fields, ind);
    2802         392 :             indirection = list_delete_first(indirection);
    2803             :         }
    2804             :     }
    2805             : 
    2806             :     /*
    2807             :      * Transform the target reference.  Typically we will get back a Param
    2808             :      * node, but there's no reason to be too picky about its type.
    2809             :      */
    2810        5376 :     target = transformExpr(pstate, (Node *) cref,
    2811             :                            EXPR_KIND_UPDATE_TARGET);
    2812        5364 :     targettype = exprType(target);
    2813        5364 :     targettypmod = exprTypmod(target);
    2814        5364 :     targetcollation = exprCollation(target);
    2815             : 
    2816             :     /*
    2817             :      * The rest mostly matches transformSelectStmt, except that we needn't
    2818             :      * consider WITH or INTO, and we build a targetlist our own way.
    2819             :      */
    2820        5364 :     qry->commandType = CMD_SELECT;
    2821        5364 :     pstate->p_is_insert = false;
    2822             : 
    2823             :     /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
    2824        5364 :     pstate->p_locking_clause = sstmt->lockingClause;
    2825             : 
    2826             :     /* make WINDOW info available for window functions, too */
    2827        5364 :     pstate->p_windowdefs = sstmt->windowClause;
    2828             : 
    2829             :     /* process the FROM clause */
    2830        5364 :     transformFromClause(pstate, sstmt->fromClause);
    2831             : 
    2832             :     /* initially transform the targetlist as if in SELECT */
    2833        5364 :     tlist = transformTargetList(pstate, sstmt->targetList,
    2834             :                                 EXPR_KIND_SELECT_TARGET);
    2835             : 
    2836             :     /* we should have exactly one targetlist item */
    2837        5364 :     if (list_length(tlist) != 1)
    2838           4 :         ereport(ERROR,
    2839             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    2840             :                  errmsg_plural("assignment source returned %d column",
    2841             :                                "assignment source returned %d columns",
    2842             :                                list_length(tlist),
    2843             :                                list_length(tlist))));
    2844             : 
    2845        5360 :     tle = linitial_node(TargetEntry, tlist);
    2846             : 
    2847             :     /*
    2848             :      * This next bit is similar to transformAssignedExpr; the key difference
    2849             :      * is we use COERCION_PLPGSQL not COERCION_ASSIGNMENT.
    2850             :      */
    2851        5360 :     type_id = exprType((Node *) tle->expr);
    2852             : 
    2853        5360 :     pstate->p_expr_kind = EXPR_KIND_UPDATE_TARGET;
    2854             : 
    2855        5360 :     if (indirection)
    2856             :     {
    2857          98 :         tle->expr = (Expr *)
    2858         108 :             transformAssignmentIndirection(pstate,
    2859             :                                            target,
    2860         108 :                                            stmt->name,
    2861             :                                            false,
    2862             :                                            targettype,
    2863             :                                            targettypmod,
    2864             :                                            targetcollation,
    2865             :                                            indirection,
    2866             :                                            list_head(indirection),
    2867         108 :                                            (Node *) tle->expr,
    2868             :                                            COERCION_PLPGSQL,
    2869             :                                            exprLocation(target));
    2870             :     }
    2871        5252 :     else if (targettype != type_id &&
    2872        1592 :              (targettype == RECORDOID || ISCOMPLEX(targettype)) &&
    2873         450 :              (type_id == RECORDOID || ISCOMPLEX(type_id)))
    2874             :     {
    2875             :         /*
    2876             :          * Hack: do not let coerce_to_target_type() deal with inconsistent
    2877             :          * composite types.  Just pass the expression result through as-is,
    2878             :          * and let the PL/pgSQL executor do the conversion its way.  This is
    2879             :          * rather bogus, but it's needed for backwards compatibility.
    2880             :          */
    2881             :     }
    2882             :     else
    2883             :     {
    2884             :         /*
    2885             :          * For normal non-qualified target column, do type checking and
    2886             :          * coercion.
    2887             :          */
    2888        4896 :         Node       *orig_expr = (Node *) tle->expr;
    2889             : 
    2890        4896 :         tle->expr = (Expr *)
    2891        4896 :             coerce_to_target_type(pstate,
    2892             :                                   orig_expr, type_id,
    2893             :                                   targettype, targettypmod,
    2894             :                                   COERCION_PLPGSQL,
    2895             :                                   COERCE_IMPLICIT_CAST,
    2896             :                                   -1);
    2897             :         /* With COERCION_PLPGSQL, this error is probably unreachable */
    2898        4896 :         if (tle->expr == NULL)
    2899           0 :             ereport(ERROR,
    2900             :                     (errcode(ERRCODE_DATATYPE_MISMATCH),
    2901             :                      errmsg("variable \"%s\" is of type %s"
    2902             :                             " but expression is of type %s",
    2903             :                             stmt->name,
    2904             :                             format_type_be(targettype),
    2905             :                             format_type_be(type_id)),
    2906             :                      errhint("You will need to rewrite or cast the expression."),
    2907             :                      parser_errposition(pstate, exprLocation(orig_expr))));
    2908             :     }
    2909             : 
    2910        5350 :     pstate->p_expr_kind = EXPR_KIND_NONE;
    2911             : 
    2912        5350 :     qry->targetList = list_make1(tle);
    2913             : 
    2914             :     /* transform WHERE */
    2915        5350 :     qual = transformWhereClause(pstate, sstmt->whereClause,
    2916             :                                 EXPR_KIND_WHERE, "WHERE");
    2917             : 
    2918             :     /* initial processing of HAVING clause is much like WHERE clause */
    2919        5350 :     qry->havingQual = transformWhereClause(pstate, sstmt->havingClause,
    2920             :                                            EXPR_KIND_HAVING, "HAVING");
    2921             : 
    2922             :     /*
    2923             :      * Transform sorting/grouping stuff.  Do ORDER BY first because both
    2924             :      * transformGroupClause and transformDistinctClause need the results. Note
    2925             :      * that these functions can also change the targetList, so it's passed to
    2926             :      * them by reference.
    2927             :      */
    2928        5350 :     qry->sortClause = transformSortClause(pstate,
    2929             :                                           sstmt->sortClause,
    2930             :                                           &qry->targetList,
    2931             :                                           EXPR_KIND_ORDER_BY,
    2932             :                                           false /* allow SQL92 rules */ );
    2933             : 
    2934        5350 :     qry->groupClause = transformGroupClause(pstate,
    2935             :                                             sstmt->groupClause,
    2936             :                                             &qry->groupingSets,
    2937             :                                             &qry->targetList,
    2938             :                                             qry->sortClause,
    2939             :                                             EXPR_KIND_GROUP_BY,
    2940             :                                             false /* allow SQL92 rules */ );
    2941             : 
    2942        5350 :     if (sstmt->distinctClause == NIL)
    2943             :     {
    2944        5350 :         qry->distinctClause = NIL;
    2945        5350 :         qry->hasDistinctOn = false;
    2946             :     }
    2947           0 :     else if (linitial(sstmt->distinctClause) == NULL)
    2948             :     {
    2949             :         /* We had SELECT DISTINCT */
    2950           0 :         qry->distinctClause = transformDistinctClause(pstate,
    2951             :                                                       &qry->targetList,
    2952             :                                                       qry->sortClause,
    2953             :                                                       false);
    2954           0 :         qry->hasDistinctOn = false;
    2955             :     }
    2956             :     else
    2957             :     {
    2958             :         /* We had SELECT DISTINCT ON */
    2959           0 :         qry->distinctClause = transformDistinctOnClause(pstate,
    2960             :                                                         sstmt->distinctClause,
    2961             :                                                         &qry->targetList,
    2962             :                                                         qry->sortClause);
    2963           0 :         qry->hasDistinctOn = true;
    2964             :     }
    2965             : 
    2966             :     /* transform LIMIT */
    2967        5350 :     qry->limitOffset = transformLimitClause(pstate, sstmt->limitOffset,
    2968             :                                             EXPR_KIND_OFFSET, "OFFSET",
    2969             :                                             sstmt->limitOption);
    2970        5350 :     qry->limitCount = transformLimitClause(pstate, sstmt->limitCount,
    2971             :                                            EXPR_KIND_LIMIT, "LIMIT",
    2972             :                                            sstmt->limitOption);
    2973        5350 :     qry->limitOption = sstmt->limitOption;
    2974             : 
    2975             :     /* transform window clauses after we have seen all window functions */
    2976        5350 :     qry->windowClause = transformWindowDefinitions(pstate,
    2977             :                                                    pstate->p_windowdefs,
    2978             :                                                    &qry->targetList);
    2979             : 
    2980        5350 :     qry->rtable = pstate->p_rtable;
    2981        5350 :     qry->rteperminfos = pstate->p_rteperminfos;
    2982        5350 :     qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
    2983             : 
    2984        5350 :     qry->hasSubLinks = pstate->p_hasSubLinks;
    2985        5350 :     qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
    2986        5350 :     qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
    2987        5350 :     qry->hasAggs = pstate->p_hasAggs;
    2988             : 
    2989        5352 :     foreach(l, sstmt->lockingClause)
    2990             :     {
    2991           2 :         transformLockingClause(pstate, qry,
    2992           2 :                                (LockingClause *) lfirst(l), false);
    2993             :     }
    2994             : 
    2995        5350 :     assign_query_collations(pstate, qry);
    2996             : 
    2997             :     /* this must be done after collations, for reliable comparison of exprs */
    2998        5350 :     if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
    2999           4 :         parseCheckAggregates(pstate, qry);
    3000             : 
    3001        5350 :     return qry;
    3002             : }
    3003             : 
    3004             : 
    3005             : /*
    3006             :  * transformDeclareCursorStmt -
    3007             :  *  transform a DECLARE CURSOR Statement
    3008             :  *
    3009             :  * DECLARE CURSOR is like other utility statements in that we emit it as a
    3010             :  * CMD_UTILITY Query node; however, we must first transform the contained
    3011             :  * query.  We used to postpone that until execution, but it's really necessary
    3012             :  * to do it during the normal parse analysis phase to ensure that side effects
    3013             :  * of parser hooks happen at the expected time.
    3014             :  */
    3015             : static Query *
    3016        4568 : transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
    3017             : {
    3018             :     Query      *result;
    3019             :     Query      *query;
    3020             : 
    3021        4568 :     if ((stmt->options & CURSOR_OPT_SCROLL) &&
    3022         240 :         (stmt->options & CURSOR_OPT_NO_SCROLL))
    3023           0 :         ereport(ERROR,
    3024             :                 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
    3025             :         /* translator: %s is a SQL keyword */
    3026             :                  errmsg("cannot specify both %s and %s",
    3027             :                         "SCROLL", "NO SCROLL")));
    3028             : 
    3029        4568 :     if ((stmt->options & CURSOR_OPT_ASENSITIVE) &&
    3030           0 :         (stmt->options & CURSOR_OPT_INSENSITIVE))
    3031           0 :         ereport(ERROR,
    3032             :                 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
    3033             :         /* translator: %s is a SQL keyword */
    3034             :                  errmsg("cannot specify both %s and %s",
    3035             :                         "ASENSITIVE", "INSENSITIVE")));
    3036             : 
    3037             :     /* Transform contained query, not allowing SELECT INTO */
    3038        4568 :     query = transformStmt(pstate, stmt->query);
    3039        4546 :     stmt->query = (Node *) query;
    3040             : 
    3041             :     /* Grammar should not have allowed anything but SELECT */
    3042        4546 :     if (!IsA(query, Query) ||
    3043        4546 :         query->commandType != CMD_SELECT)
    3044           0 :         elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR");
    3045             : 
    3046             :     /*
    3047             :      * We also disallow data-modifying WITH in a cursor.  (This could be
    3048             :      * allowed, but the semantics of when the updates occur might be
    3049             :      * surprising.)
    3050             :      */
    3051        4546 :     if (query->hasModifyingCTE)
    3052           0 :         ereport(ERROR,
    3053             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3054             :                  errmsg("DECLARE CURSOR must not contain data-modifying statements in WITH")));
    3055             : 
    3056             :     /* FOR UPDATE and WITH HOLD are not compatible */
    3057        4546 :     if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
    3058           0 :         ereport(ERROR,
    3059             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3060             :         /*------
    3061             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    3062             :                  errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
    3063             :                         LCS_asString(((RowMarkClause *)
    3064             :                                       linitial(query->rowMarks))->strength)),
    3065             :                  errdetail("Holdable cursors must be READ ONLY.")));
    3066             : 
    3067             :     /* FOR UPDATE and SCROLL are not compatible */
    3068        4546 :     if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
    3069           0 :         ereport(ERROR,
    3070             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3071             :         /*------
    3072             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    3073             :                  errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
    3074             :                         LCS_asString(((RowMarkClause *)
    3075             :                                       linitial(query->rowMarks))->strength)),
    3076             :                  errdetail("Scrollable cursors must be READ ONLY.")));
    3077             : 
    3078             :     /* FOR UPDATE and INSENSITIVE are not compatible */
    3079        4546 :     if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
    3080           0 :         ereport(ERROR,
    3081             :                 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
    3082             :         /*------
    3083             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    3084             :                  errmsg("DECLARE INSENSITIVE CURSOR ... %s is not valid",
    3085             :                         LCS_asString(((RowMarkClause *)
    3086             :                                       linitial(query->rowMarks))->strength)),
    3087             :                  errdetail("Insensitive cursors must be READ ONLY.")));
    3088             : 
    3089             :     /* represent the command as a utility Query */
    3090        4546 :     result = makeNode(Query);
    3091        4546 :     result->commandType = CMD_UTILITY;
    3092        4546 :     result->utilityStmt = (Node *) stmt;
    3093             : 
    3094        4546 :     return result;
    3095             : }
    3096             : 
    3097             : 
    3098             : /*
    3099             :  * transformExplainStmt -
    3100             :  *  transform an EXPLAIN Statement
    3101             :  *
    3102             :  * EXPLAIN is like other utility statements in that we emit it as a
    3103             :  * CMD_UTILITY Query node; however, we must first transform the contained
    3104             :  * query.  We used to postpone that until execution, but it's really necessary
    3105             :  * to do it during the normal parse analysis phase to ensure that side effects
    3106             :  * of parser hooks happen at the expected time.
    3107             :  */
    3108             : static Query *
    3109       23904 : transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
    3110             : {
    3111             :     Query      *result;
    3112       23904 :     bool        generic_plan = false;
    3113       23904 :     Oid        *paramTypes = NULL;
    3114       23904 :     int         numParams = 0;
    3115             : 
    3116             :     /*
    3117             :      * If we have no external source of parameter definitions, and the
    3118             :      * GENERIC_PLAN option is specified, then accept variable parameter
    3119             :      * definitions (similarly to PREPARE, for example).
    3120             :      */
    3121       23904 :     if (pstate->p_paramref_hook == NULL)
    3122             :     {
    3123             :         ListCell   *lc;
    3124             : 
    3125       46284 :         foreach(lc, stmt->options)
    3126             :         {
    3127       22398 :             DefElem    *opt = (DefElem *) lfirst(lc);
    3128             : 
    3129       22398 :             if (strcmp(opt->defname, "generic_plan") == 0)
    3130          18 :                 generic_plan = defGetBoolean(opt);
    3131             :             /* don't "break", as we want the last value */
    3132             :         }
    3133       23886 :         if (generic_plan)
    3134          18 :             setup_parse_variable_parameters(pstate, &paramTypes, &numParams);
    3135             :     }
    3136             : 
    3137             :     /* transform contained query, allowing SELECT INTO */
    3138       23904 :     stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
    3139             : 
    3140             :     /* make sure all is well with parameter types */
    3141       23896 :     if (generic_plan)
    3142          18 :         check_variable_parameters(pstate, (Query *) stmt->query);
    3143             : 
    3144             :     /* represent the command as a utility Query */
    3145       23896 :     result = makeNode(Query);
    3146       23896 :     result->commandType = CMD_UTILITY;
    3147       23896 :     result->utilityStmt = (Node *) stmt;
    3148             : 
    3149       23896 :     return result;
    3150             : }
    3151             : 
    3152             : 
    3153             : /*
    3154             :  * transformCreateTableAsStmt -
    3155             :  *  transform a CREATE TABLE AS, SELECT ... INTO, or CREATE MATERIALIZED VIEW
    3156             :  *  Statement
    3157             :  *
    3158             :  * As with DECLARE CURSOR and EXPLAIN, transform the contained statement now.
    3159             :  */
    3160             : static Query *
    3161        1996 : transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
    3162             : {
    3163             :     Query      *result;
    3164             :     Query      *query;
    3165             : 
    3166             :     /* transform contained query, not allowing SELECT INTO */
    3167        1996 :     query = transformStmt(pstate, stmt->query);
    3168        1992 :     stmt->query = (Node *) query;
    3169             : 
    3170             :     /* additional work needed for CREATE MATERIALIZED VIEW */
    3171        1992 :     if (stmt->objtype == OBJECT_MATVIEW)
    3172             :     {
    3173             :         /*
    3174             :          * Prohibit a data-modifying CTE in the query used to create a
    3175             :          * materialized view. It's not sufficiently clear what the user would
    3176             :          * want to happen if the MV is refreshed or incrementally maintained.
    3177             :          */
    3178         578 :         if (query->hasModifyingCTE)
    3179           0 :             ereport(ERROR,
    3180             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3181             :                      errmsg("materialized views must not use data-modifying statements in WITH")));
    3182             : 
    3183             :         /*
    3184             :          * Check whether any temporary database objects are used in the
    3185             :          * creation query. It would be hard to refresh data or incrementally
    3186             :          * maintain it if a source disappeared.
    3187             :          */
    3188         578 :         if (isQueryUsingTempRelation(query))
    3189           0 :             ereport(ERROR,
    3190             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3191             :                      errmsg("materialized views must not use temporary tables or views")));
    3192             : 
    3193             :         /*
    3194             :          * A materialized view would either need to save parameters for use in
    3195             :          * maintaining/loading the data or prohibit them entirely.  The latter
    3196             :          * seems safer and more sane.
    3197             :          */
    3198         578 :         if (query_contains_extern_params(query))
    3199           0 :             ereport(ERROR,
    3200             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3201             :                      errmsg("materialized views may not be defined using bound parameters")));
    3202             : 
    3203             :         /*
    3204             :          * For now, we disallow unlogged materialized views, because it seems
    3205             :          * like a bad idea for them to just go to empty after a crash. (If we
    3206             :          * could mark them as unpopulated, that would be better, but that
    3207             :          * requires catalog changes which crash recovery can't presently
    3208             :          * handle.)
    3209             :          */
    3210         578 :         if (stmt->into->rel->relpersistence == RELPERSISTENCE_UNLOGGED)
    3211           0 :             ereport(ERROR,
    3212             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3213             :                      errmsg("materialized views cannot be unlogged")));
    3214             : 
    3215             :         /*
    3216             :          * At runtime, we'll need a copy of the parsed-but-not-rewritten Query
    3217             :          * for purposes of creating the view's ON SELECT rule.  We stash that
    3218             :          * in the IntoClause because that's where intorel_startup() can
    3219             :          * conveniently get it from.
    3220             :          */
    3221         578 :         stmt->into->viewQuery = copyObject(query);
    3222             :     }
    3223             : 
    3224             :     /* represent the command as a utility Query */
    3225        1992 :     result = makeNode(Query);
    3226        1992 :     result->commandType = CMD_UTILITY;
    3227        1992 :     result->utilityStmt = (Node *) stmt;
    3228             : 
    3229        1992 :     return result;
    3230             : }
    3231             : 
    3232             : /*
    3233             :  * transform a CallStmt
    3234             :  */
    3235             : static Query *
    3236         522 : transformCallStmt(ParseState *pstate, CallStmt *stmt)
    3237             : {
    3238             :     List       *targs;
    3239             :     ListCell   *lc;
    3240             :     Node       *node;
    3241             :     FuncExpr   *fexpr;
    3242             :     HeapTuple   proctup;
    3243             :     Datum       proargmodes;
    3244             :     bool        isNull;
    3245         522 :     List       *outargs = NIL;
    3246             :     Query      *result;
    3247             : 
    3248             :     /*
    3249             :      * First, do standard parse analysis on the procedure call and its
    3250             :      * arguments, allowing us to identify the called procedure.
    3251             :      */
    3252         522 :     targs = NIL;
    3253        1274 :     foreach(lc, stmt->funccall->args)
    3254             :     {
    3255         752 :         targs = lappend(targs, transformExpr(pstate,
    3256         752 :                                              (Node *) lfirst(lc),
    3257             :                                              EXPR_KIND_CALL_ARGUMENT));
    3258             :     }
    3259             : 
    3260         522 :     node = ParseFuncOrColumn(pstate,
    3261         522 :                              stmt->funccall->funcname,
    3262             :                              targs,
    3263             :                              pstate->p_last_srf,
    3264             :                              stmt->funccall,
    3265             :                              true,
    3266         522 :                              stmt->funccall->location);
    3267             : 
    3268         490 :     assign_expr_collations(pstate, node);
    3269             : 
    3270         490 :     fexpr = castNode(FuncExpr, node);
    3271             : 
    3272         490 :     proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
    3273         490 :     if (!HeapTupleIsValid(proctup))
    3274           0 :         elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
    3275             : 
    3276             :     /*
    3277             :      * Expand the argument list to deal with named-argument notation and
    3278             :      * default arguments.  For ordinary FuncExprs this'd be done during
    3279             :      * planning, but a CallStmt doesn't go through planning, and there seems
    3280             :      * no good reason not to do it here.
    3281             :      */
    3282         490 :     fexpr->args = expand_function_arguments(fexpr->args,
    3283             :                                             true,
    3284             :                                             fexpr->funcresulttype,
    3285             :                                             proctup);
    3286             : 
    3287             :     /* Fetch proargmodes; if it's null, there are no output args */
    3288         490 :     proargmodes = SysCacheGetAttr(PROCOID, proctup,
    3289             :                                   Anum_pg_proc_proargmodes,
    3290             :                                   &isNull);
    3291         490 :     if (!isNull)
    3292             :     {
    3293             :         /*
    3294             :          * Split the list into input arguments in fexpr->args and output
    3295             :          * arguments in stmt->outargs.  INOUT arguments appear in both lists.
    3296             :          */
    3297             :         ArrayType  *arr;
    3298             :         int         numargs;
    3299             :         char       *argmodes;
    3300             :         List       *inargs;
    3301             :         int         i;
    3302             : 
    3303         202 :         arr = DatumGetArrayTypeP(proargmodes);  /* ensure not toasted */
    3304         202 :         numargs = list_length(fexpr->args);
    3305         202 :         if (ARR_NDIM(arr) != 1 ||
    3306         202 :             ARR_DIMS(arr)[0] != numargs ||
    3307         202 :             ARR_HASNULL(arr) ||
    3308         202 :             ARR_ELEMTYPE(arr) != CHAROID)
    3309           0 :             elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
    3310             :                  numargs);
    3311         202 :         argmodes = (char *) ARR_DATA_PTR(arr);
    3312             : 
    3313         202 :         inargs = NIL;
    3314         202 :         i = 0;
    3315         676 :         foreach(lc, fexpr->args)
    3316             :         {
    3317         474 :             Node       *n = lfirst(lc);
    3318             : 
    3319         474 :             switch (argmodes[i])
    3320             :             {
    3321         156 :                 case PROARGMODE_IN:
    3322             :                 case PROARGMODE_VARIADIC:
    3323         156 :                     inargs = lappend(inargs, n);
    3324         156 :                     break;
    3325         116 :                 case PROARGMODE_OUT:
    3326         116 :                     outargs = lappend(outargs, n);
    3327         116 :                     break;
    3328         202 :                 case PROARGMODE_INOUT:
    3329         202 :                     inargs = lappend(inargs, n);
    3330         202 :                     outargs = lappend(outargs, copyObject(n));
    3331         202 :                     break;
    3332           0 :                 default:
    3333             :                     /* note we don't support PROARGMODE_TABLE */
    3334           0 :                     elog(ERROR, "invalid argmode %c for procedure",
    3335             :                          argmodes[i]);
    3336             :                     break;
    3337             :             }
    3338         474 :             i++;
    3339             :         }
    3340         202 :         fexpr->args = inargs;
    3341             :     }
    3342             : 
    3343         490 :     stmt->funcexpr = fexpr;
    3344         490 :     stmt->outargs = outargs;
    3345             : 
    3346         490 :     ReleaseSysCache(proctup);
    3347             : 
    3348             :     /* represent the command as a utility Query */
    3349         490 :     result = makeNode(Query);
    3350         490 :     result->commandType = CMD_UTILITY;
    3351         490 :     result->utilityStmt = (Node *) stmt;
    3352             : 
    3353         490 :     return result;
    3354             : }
    3355             : 
    3356             : /*
    3357             :  * Produce a string representation of a LockClauseStrength value.
    3358             :  * This should only be applied to valid values (not LCS_NONE).
    3359             :  */
    3360             : const char *
    3361          48 : LCS_asString(LockClauseStrength strength)
    3362             : {
    3363          48 :     switch (strength)
    3364             :     {
    3365           0 :         case LCS_NONE:
    3366             :             Assert(false);
    3367           0 :             break;
    3368           0 :         case LCS_FORKEYSHARE:
    3369           0 :             return "FOR KEY SHARE";
    3370           0 :         case LCS_FORSHARE:
    3371           0 :             return "FOR SHARE";
    3372           6 :         case LCS_FORNOKEYUPDATE:
    3373           6 :             return "FOR NO KEY UPDATE";
    3374          42 :         case LCS_FORUPDATE:
    3375          42 :             return "FOR UPDATE";
    3376             :     }
    3377           0 :     return "FOR some";            /* shouldn't happen */
    3378             : }
    3379             : 
    3380             : /*
    3381             :  * Check for features that are not supported with FOR [KEY] UPDATE/SHARE.
    3382             :  *
    3383             :  * exported so planner can check again after rewriting, query pullup, etc
    3384             :  */
    3385             : void
    3386       13004 : CheckSelectLocking(Query *qry, LockClauseStrength strength)
    3387             : {
    3388             :     Assert(strength != LCS_NONE);   /* else caller error */
    3389             : 
    3390       13004 :     if (qry->setOperations)
    3391           0 :         ereport(ERROR,
    3392             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3393             :         /*------
    3394             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    3395             :                  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
    3396             :                         LCS_asString(strength))));
    3397       13004 :     if (qry->distinctClause != NIL)
    3398           0 :         ereport(ERROR,
    3399             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3400             :         /*------
    3401             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    3402             :                  errmsg("%s is not allowed with DISTINCT clause",
    3403             :                         LCS_asString(strength))));
    3404       13004 :     if (qry->groupClause != NIL || qry->groupingSets != NIL)
    3405          12 :         ereport(ERROR,
    3406             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3407             :         /*------
    3408             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    3409             :                  errmsg("%s is not allowed with GROUP BY clause",
    3410             :                         LCS_asString(strength))));
    3411       12992 :     if (qry->havingQual != NULL)
    3412           0 :         ereport(ERROR,
    3413             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3414             :         /*------
    3415             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    3416             :                  errmsg("%s is not allowed with HAVING clause",
    3417             :                         LCS_asString(strength))));
    3418       12992 :     if (qry->hasAggs)
    3419           6 :         ereport(ERROR,
    3420             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3421             :         /*------
    3422             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    3423             :                  errmsg("%s is not allowed with aggregate functions",
    3424             :                         LCS_asString(strength))));
    3425       12986 :     if (qry->hasWindowFuncs)
    3426           0 :         ereport(ERROR,
    3427             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3428             :         /*------
    3429             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    3430             :                  errmsg("%s is not allowed with window functions",
    3431             :                         LCS_asString(strength))));
    3432       12986 :     if (qry->hasTargetSRFs)
    3433           0 :         ereport(ERROR,
    3434             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3435             :         /*------
    3436             :           translator: %s is a SQL row locking clause such as FOR UPDATE */
    3437             :                  errmsg("%s is not allowed with set-returning functions in the target list",
    3438             :                         LCS_asString(strength))));
    3439       12986 : }
    3440             : 
    3441             : /*
    3442             :  * Transform a FOR [KEY] UPDATE/SHARE clause
    3443             :  *
    3444             :  * This basically involves replacing names by integer relids.
    3445             :  *
    3446             :  * NB: if you need to change this, see also markQueryForLocking()
    3447             :  * in rewriteHandler.c, and isLockedRefname() in parse_relation.c.
    3448             :  */
    3449             : static void
    3450        5236 : transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc,
    3451             :                        bool pushedDown)
    3452             : {
    3453        5236 :     List       *lockedRels = lc->lockedRels;
    3454             :     ListCell   *l;
    3455             :     ListCell   *rt;
    3456             :     Index       i;
    3457             :     LockingClause *allrels;
    3458             : 
    3459        5236 :     CheckSelectLocking(qry, lc->strength);
    3460             : 
    3461             :     /* make a clause we can pass down to subqueries to select all rels */
    3462        5218 :     allrels = makeNode(LockingClause);
    3463        5218 :     allrels->lockedRels = NIL;   /* indicates all rels */
    3464        5218 :     allrels->strength = lc->strength;
    3465        5218 :     allrels->waitPolicy = lc->waitPolicy;
    3466             : 
    3467        5218 :     if (lockedRels == NIL)
    3468             :     {
    3469             :         /*
    3470             :          * Lock all regular tables used in query and its subqueries.  We
    3471             :          * examine inFromCl to exclude auto-added RTEs, particularly NEW/OLD
    3472             :          * in rules.  This is a bit of an abuse of a mostly-obsolete flag, but
    3473             :          * it's convenient.  We can't rely on the namespace mechanism that has
    3474             :          * largely replaced inFromCl, since for example we need to lock
    3475             :          * base-relation RTEs even if they are masked by upper joins.
    3476             :          */
    3477        1760 :         i = 0;
    3478        3612 :         foreach(rt, qry->rtable)
    3479             :         {
    3480        1852 :             RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
    3481             : 
    3482        1852 :             ++i;
    3483        1852 :             if (!rte->inFromCl)
    3484          12 :                 continue;
    3485        1840 :             switch (rte->rtekind)
    3486             :             {
    3487        1810 :                 case RTE_RELATION:
    3488             :                     {
    3489             :                         RTEPermissionInfo *perminfo;
    3490             : 
    3491        1810 :                         applyLockingClause(qry, i,
    3492             :                                            lc->strength,
    3493             :                                            lc->waitPolicy,
    3494             :                                            pushedDown);
    3495        1810 :                         perminfo = getRTEPermissionInfo(qry->rteperminfos, rte);
    3496        1810 :                         perminfo->requiredPerms |= ACL_SELECT_FOR_UPDATE;
    3497             :                     }
    3498        1810 :                     break;
    3499           0 :                 case RTE_SUBQUERY:
    3500           0 :                     applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
    3501             :                                        pushedDown);
    3502             : 
    3503             :                     /*
    3504             :                      * FOR UPDATE/SHARE of subquery is propagated to all of
    3505             :                      * subquery's rels, too.  We could do this later (based on
    3506             :                      * the marking of the subquery RTE) but it is convenient
    3507             :                      * to have local knowledge in each query level about which
    3508             :                      * rels need to be opened with RowShareLock.
    3509             :                      */
    3510           0 :                     transformLockingClause(pstate, rte->subquery,
    3511             :                                            allrels, true);
    3512           0 :                     break;
    3513          30 :                 default:
    3514             :                     /* ignore JOIN, SPECIAL, FUNCTION, VALUES, CTE RTEs */
    3515          30 :                     break;
    3516             :             }
    3517             :         }
    3518             :     }
    3519             :     else
    3520             :     {
    3521             :         /*
    3522             :          * Lock just the named tables.  As above, we allow locking any base
    3523             :          * relation regardless of alias-visibility rules, so we need to
    3524             :          * examine inFromCl to exclude OLD/NEW.
    3525             :          */
    3526        6904 :         foreach(l, lockedRels)
    3527             :         {
    3528        3470 :             RangeVar   *thisrel = (RangeVar *) lfirst(l);
    3529             : 
    3530             :             /* For simplicity we insist on unqualified alias names here */
    3531        3470 :             if (thisrel->catalogname || thisrel->schemaname)
    3532           0 :                 ereport(ERROR,
    3533             :                         (errcode(ERRCODE_SYNTAX_ERROR),
    3534             :                 /*------
    3535             :                   translator: %s is a SQL row locking clause such as FOR UPDATE */
    3536             :                          errmsg("%s must specify unqualified relation names",
    3537             :                                 LCS_asString(lc->strength)),
    3538             :                          parser_errposition(pstate, thisrel->location)));
    3539             : 
    3540        3470 :             i = 0;
    3541        3818 :             foreach(rt, qry->rtable)
    3542             :             {
    3543        3806 :                 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
    3544        3806 :                 char       *rtename = rte->eref->aliasname;
    3545             : 
    3546        3806 :                 ++i;
    3547        3806 :                 if (!rte->inFromCl)
    3548          24 :                     continue;
    3549             : 
    3550             :                 /*
    3551             :                  * A join RTE without an alias is not visible as a relation
    3552             :                  * name and needs to be skipped (otherwise it might hide a
    3553             :                  * base relation with the same name), except if it has a USING
    3554             :                  * alias, which *is* visible.
    3555             :                  *
    3556             :                  * Subquery and values RTEs without aliases are never visible
    3557             :                  * as relation names and must always be skipped.
    3558             :                  */
    3559        3782 :                 if (rte->alias == NULL)
    3560             :                 {
    3561         174 :                     if (rte->rtekind == RTE_JOIN)
    3562             :                     {
    3563          74 :                         if (rte->join_using_alias == NULL)
    3564          62 :                             continue;
    3565          12 :                         rtename = rte->join_using_alias->aliasname;
    3566             :                     }
    3567         100 :                     else if (rte->rtekind == RTE_SUBQUERY ||
    3568          94 :                              rte->rtekind == RTE_VALUES)
    3569           6 :                         continue;
    3570             :                 }
    3571             : 
    3572        3714 :                 if (strcmp(rtename, thisrel->relname) == 0)
    3573             :                 {
    3574        3458 :                     switch (rte->rtekind)
    3575             :                     {
    3576        3434 :                         case RTE_RELATION:
    3577             :                             {
    3578             :                                 RTEPermissionInfo *perminfo;
    3579             : 
    3580        3434 :                                 applyLockingClause(qry, i,
    3581             :                                                    lc->strength,
    3582             :                                                    lc->waitPolicy,
    3583             :                                                    pushedDown);
    3584        3434 :                                 perminfo = getRTEPermissionInfo(qry->rteperminfos, rte);
    3585        3434 :                                 perminfo->requiredPerms |= ACL_SELECT_FOR_UPDATE;
    3586             :                             }
    3587        3434 :                             break;
    3588          12 :                         case RTE_SUBQUERY:
    3589          12 :                             applyLockingClause(qry, i, lc->strength,
    3590             :                                                lc->waitPolicy, pushedDown);
    3591             :                             /* see comment above */
    3592          12 :                             transformLockingClause(pstate, rte->subquery,
    3593             :                                                    allrels, true);
    3594          12 :                             break;
    3595          12 :                         case RTE_JOIN:
    3596          12 :                             ereport(ERROR,
    3597             :                                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3598             :                             /*------
    3599             :                               translator: %s is a SQL row locking clause such as FOR UPDATE */
    3600             :                                      errmsg("%s cannot be applied to a join",
    3601             :                                             LCS_asString(lc->strength)),
    3602             :                                      parser_errposition(pstate, thisrel->location)));
    3603             :                             break;
    3604           0 :                         case RTE_FUNCTION:
    3605           0 :                             ereport(ERROR,
    3606             :                                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3607             :                             /*------
    3608             :                               translator: %s is a SQL row locking clause such as FOR UPDATE */
    3609             :                                      errmsg("%s cannot be applied to a function",
    3610             :                                             LCS_asString(lc->strength)),
    3611             :                                      parser_errposition(pstate, thisrel->location)));
    3612             :                             break;
    3613           0 :                         case RTE_TABLEFUNC:
    3614           0 :                             ereport(ERROR,
    3615             :                                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3616             :                             /*------
    3617             :                               translator: %s is a SQL row locking clause such as FOR UPDATE */
    3618             :                                      errmsg("%s cannot be applied to a table function",
    3619             :                                             LCS_asString(lc->strength)),
    3620             :                                      parser_errposition(pstate, thisrel->location)));
    3621             :                             break;
    3622           0 :                         case RTE_VALUES:
    3623           0 :                             ereport(ERROR,
    3624             :                                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3625             :                             /*------
    3626             :                               translator: %s is a SQL row locking clause such as FOR UPDATE */
    3627             :                                      errmsg("%s cannot be applied to VALUES",
    3628             :                                             LCS_asString(lc->strength)),
    3629             :                                      parser_errposition(pstate, thisrel->location)));
    3630             :                             break;
    3631           0 :                         case RTE_CTE:
    3632           0 :                             ereport(ERROR,
    3633             :                                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3634             :                             /*------
    3635             :                               translator: %s is a SQL row locking clause such as FOR UPDATE */
    3636             :                                      errmsg("%s cannot be applied to a WITH query",
    3637             :                                             LCS_asString(lc->strength)),
    3638             :                                      parser_errposition(pstate, thisrel->location)));
    3639             :                             break;
    3640           0 :                         case RTE_NAMEDTUPLESTORE:
    3641           0 :                             ereport(ERROR,
    3642             :                                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3643             :                             /*------
    3644             :                               translator: %s is a SQL row locking clause such as FOR UPDATE */
    3645             :                                      errmsg("%s cannot be applied to a named tuplestore",
    3646             :                                             LCS_asString(lc->strength)),
    3647             :                                      parser_errposition(pstate, thisrel->location)));
    3648             :                             break;
    3649             : 
    3650             :                             /* Shouldn't be possible to see RTE_RESULT here */
    3651             : 
    3652           0 :                         default:
    3653           0 :                             elog(ERROR, "unrecognized RTE type: %d",
    3654             :                                  (int) rte->rtekind);
    3655             :                             break;
    3656             :                     }
    3657        3446 :                     break;      /* out of foreach loop */
    3658             :                 }
    3659             :             }
    3660        3458 :             if (rt == NULL)
    3661          12 :                 ereport(ERROR,
    3662             :                         (errcode(ERRCODE_UNDEFINED_TABLE),
    3663             :                 /*------
    3664             :                   translator: %s is a SQL row locking clause such as FOR UPDATE */
    3665             :                          errmsg("relation \"%s\" in %s clause not found in FROM clause",
    3666             :                                 thisrel->relname,
    3667             :                                 LCS_asString(lc->strength)),
    3668             :                          parser_errposition(pstate, thisrel->location)));
    3669             :         }
    3670             :     }
    3671        5194 : }
    3672             : 
    3673             : /*
    3674             :  * Record locking info for a single rangetable item
    3675             :  */
    3676             : void
    3677        5352 : applyLockingClause(Query *qry, Index rtindex,
    3678             :                    LockClauseStrength strength, LockWaitPolicy waitPolicy,
    3679             :                    bool pushedDown)
    3680             : {
    3681             :     RowMarkClause *rc;
    3682             : 
    3683             :     Assert(strength != LCS_NONE);   /* else caller error */
    3684             : 
    3685             :     /* If it's an explicit clause, make sure hasForUpdate gets set */
    3686        5352 :     if (!pushedDown)
    3687        5252 :         qry->hasForUpdate = true;
    3688             : 
    3689             :     /* Check for pre-existing entry for same rtindex */
    3690        5352 :     if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
    3691             :     {
    3692             :         /*
    3693             :          * If the same RTE is specified with more than one locking strength,
    3694             :          * use the strongest.  (Reasonable, since you can't take both a shared
    3695             :          * and exclusive lock at the same time; it'll end up being exclusive
    3696             :          * anyway.)
    3697             :          *
    3698             :          * Similarly, if the same RTE is specified with more than one lock
    3699             :          * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
    3700             :          * turn wins over waiting for the lock (the default).  This is a bit
    3701             :          * more debatable but raising an error doesn't seem helpful. (Consider
    3702             :          * for instance SELECT FOR UPDATE NOWAIT from a view that internally
    3703             :          * contains a plain FOR UPDATE spec.)  Having NOWAIT win over SKIP
    3704             :          * LOCKED is reasonable since the former throws an error in case of
    3705             :          * coming across a locked tuple, which may be undesirable in some
    3706             :          * cases but it seems better than silently returning inconsistent
    3707             :          * results.
    3708             :          *
    3709             :          * And of course pushedDown becomes false if any clause is explicit.
    3710             :          */
    3711           0 :         rc->strength = Max(rc->strength, strength);
    3712           0 :         rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
    3713           0 :         rc->pushedDown &= pushedDown;
    3714           0 :         return;
    3715             :     }
    3716             : 
    3717             :     /* Make a new RowMarkClause */
    3718        5352 :     rc = makeNode(RowMarkClause);
    3719        5352 :     rc->rti = rtindex;
    3720        5352 :     rc->strength = strength;
    3721        5352 :     rc->waitPolicy = waitPolicy;
    3722        5352 :     rc->pushedDown = pushedDown;
    3723        5352 :     qry->rowMarks = lappend(qry->rowMarks, rc);
    3724             : }
    3725             : 
    3726             : #ifdef DEBUG_NODE_TESTS_ENABLED
    3727             : /*
    3728             :  * Coverage testing for raw_expression_tree_walker().
    3729             :  *
    3730             :  * When enabled, we run raw_expression_tree_walker() over every DML statement
    3731             :  * submitted to parse analysis.  Without this provision, that function is only
    3732             :  * applied in limited cases involving CTEs, and we don't really want to have
    3733             :  * to test everything inside as well as outside a CTE.
    3734             :  */
    3735             : static bool
    3736    25971098 : test_raw_expression_coverage(Node *node, void *context)
    3737             : {
    3738    25971098 :     if (node == NULL)
    3739    13980854 :         return false;
    3740    11990244 :     return raw_expression_tree_walker(node,
    3741             :                                       test_raw_expression_coverage,
    3742             :                                       context);
    3743             : }
    3744             : #endif                          /* DEBUG_NODE_TESTS_ENABLED */

Generated by: LCOV version 1.16