PostgreSQL Source Code  git master
analyze.c File Reference
#include "postgres.h"
#include "access/sysattr.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/var.h"
#include "parser/analyze.h"
#include "parser/parse_agg.h"
#include "parser/parse_clause.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_cte.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parse_param.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteManip.h"
#include "utils/rel.h"
Include dependency graph for analyze.c:

Go to the source code of this file.

Functions

static QuerytransformOptionalSelectInto (ParseState *pstate, Node *parseTree)
 
static QuerytransformDeleteStmt (ParseState *pstate, DeleteStmt *stmt)
 
static QuerytransformInsertStmt (ParseState *pstate, InsertStmt *stmt)
 
static ListtransformInsertRow (ParseState *pstate, List *exprlist, List *stmtcols, List *icolumns, List *attrnos, bool strip_indirection)
 
static OnConflictExprtransformOnConflictClause (ParseState *pstate, OnConflictClause *onConflictClause)
 
static int count_rowexpr_columns (ParseState *pstate, Node *expr)
 
static QuerytransformSelectStmt (ParseState *pstate, SelectStmt *stmt)
 
static QuerytransformValuesClause (ParseState *pstate, SelectStmt *stmt)
 
static QuerytransformSetOperationStmt (ParseState *pstate, SelectStmt *stmt)
 
static NodetransformSetOperationTree (ParseState *pstate, SelectStmt *stmt, bool isTopLevel, List **targetlist)
 
static void determineRecursiveColTypes (ParseState *pstate, Node *larg, List *nrtargetlist)
 
static QuerytransformUpdateStmt (ParseState *pstate, UpdateStmt *stmt)
 
static ListtransformReturningList (ParseState *pstate, List *returningList)
 
static ListtransformUpdateTargetList (ParseState *pstate, List *targetList)
 
static QuerytransformDeclareCursorStmt (ParseState *pstate, DeclareCursorStmt *stmt)
 
static QuerytransformExplainStmt (ParseState *pstate, ExplainStmt *stmt)
 
static QuerytransformCreateTableAsStmt (ParseState *pstate, CreateTableAsStmt *stmt)
 
static QuerytransformCallStmt (ParseState *pstate, CallStmt *stmt)
 
static void transformLockingClause (ParseState *pstate, Query *qry, LockingClause *lc, bool pushedDown)
 
Queryparse_analyze (RawStmt *parseTree, const char *sourceText, Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
 
Queryparse_analyze_varparams (RawStmt *parseTree, const char *sourceText, Oid **paramTypes, int *numParams)
 
Queryparse_sub_analyze (Node *parseTree, ParseState *parentParseState, CommonTableExpr *parentCTE, bool locked_from_parent, bool resolve_unknowns)
 
QuerytransformTopLevelStmt (ParseState *pstate, RawStmt *parseTree)
 
QuerytransformStmt (ParseState *pstate, Node *parseTree)
 
bool analyze_requires_snapshot (RawStmt *parseTree)
 
const char * LCS_asString (LockClauseStrength strength)
 
void CheckSelectLocking (Query *qry, LockClauseStrength strength)
 
void applyLockingClause (Query *qry, Index rtindex, LockClauseStrength strength, LockWaitPolicy waitPolicy, bool pushedDown)
 

Variables

post_parse_analyze_hook_type post_parse_analyze_hook = NULL
 

Function Documentation

◆ analyze_requires_snapshot()

bool analyze_requires_snapshot ( RawStmt parseTree)

Definition at line 356 of file analyze.c.

References nodeTag, RawStmt::stmt, T_CreateTableAsStmt, T_DeclareCursorStmt, T_DeleteStmt, T_ExplainStmt, T_InsertStmt, T_SelectStmt, and T_UpdateStmt.

Referenced by BuildCachedPlan(), exec_bind_message(), exec_parse_message(), and exec_simple_query().

357 {
358  bool result;
359 
360  switch (nodeTag(parseTree->stmt))
361  {
362  /*
363  * Optimizable statements
364  */
365  case T_InsertStmt:
366  case T_DeleteStmt:
367  case T_UpdateStmt:
368  case T_SelectStmt:
369  result = true;
370  break;
371 
372  /*
373  * Special cases
374  */
375  case T_DeclareCursorStmt:
376  case T_ExplainStmt:
377  case T_CreateTableAsStmt:
378  /* yes, because we must analyze the contained statement */
379  result = true;
380  break;
381 
382  default:
383  /* other utility statements don't have any real parse analysis */
384  result = false;
385  break;
386  }
387 
388  return result;
389 }
Node * stmt
Definition: parsenodes.h:1447
#define nodeTag(nodeptr)
Definition: nodes.h:518

◆ applyLockingClause()

void applyLockingClause ( Query qry,
Index  rtindex,
LockClauseStrength  strength,
LockWaitPolicy  waitPolicy,
bool  pushedDown 
)

Definition at line 2885 of file analyze.c.

References Assert, get_parse_rowmark(), Query::hasForUpdate, lappend(), LCS_NONE, makeNode, Max, RowMarkClause::pushedDown, raw_expression_tree_walker(), Query::rowMarks, RowMarkClause::rti, RowMarkClause::strength, and RowMarkClause::waitPolicy.

Referenced by markQueryForLocking(), and transformLockingClause().

2888 {
2889  RowMarkClause *rc;
2890 
2891  Assert(strength != LCS_NONE); /* else caller error */
2892 
2893  /* If it's an explicit clause, make sure hasForUpdate gets set */
2894  if (!pushedDown)
2895  qry->hasForUpdate = true;
2896 
2897  /* Check for pre-existing entry for same rtindex */
2898  if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
2899  {
2900  /*
2901  * If the same RTE is specified with more than one locking strength,
2902  * use the strongest. (Reasonable, since you can't take both a shared
2903  * and exclusive lock at the same time; it'll end up being exclusive
2904  * anyway.)
2905  *
2906  * Similarly, if the same RTE is specified with more than one lock
2907  * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
2908  * turn wins over waiting for the lock (the default). This is a bit
2909  * more debatable but raising an error doesn't seem helpful. (Consider
2910  * for instance SELECT FOR UPDATE NOWAIT from a view that internally
2911  * contains a plain FOR UPDATE spec.) Having NOWAIT win over SKIP
2912  * LOCKED is reasonable since the former throws an error in case of
2913  * coming across a locked tuple, which may be undesirable in some
2914  * cases but it seems better than silently returning inconsistent
2915  * results.
2916  *
2917  * And of course pushedDown becomes false if any clause is explicit.
2918  */
2919  rc->strength = Max(rc->strength, strength);
2920  rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
2921  rc->pushedDown &= pushedDown;
2922  return;
2923  }
2924 
2925  /* Make a new RowMarkClause */
2926  rc = makeNode(RowMarkClause);
2927  rc->rti = rtindex;
2928  rc->strength = strength;
2929  rc->waitPolicy = waitPolicy;
2930  rc->pushedDown = pushedDown;
2931  qry->rowMarks = lappend(qry->rowMarks, rc);
2932 }
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
List * rowMarks
Definition: parsenodes.h:161
LockClauseStrength strength
Definition: parsenodes.h:1330
List * lappend(List *list, void *datum)
Definition: list.c:128
#define Max(x, y)
Definition: c.h:840
#define makeNode(_type_)
Definition: nodes.h:561
#define Assert(condition)
Definition: c.h:688
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1331
bool hasForUpdate
Definition: parsenodes.h:130

◆ CheckSelectLocking()

void CheckSelectLocking ( Query qry,
LockClauseStrength  strength 
)

Definition at line 2650 of file analyze.c.

References Assert, Query::distinctClause, ereport, errcode(), errmsg(), ERROR, Query::groupClause, Query::hasAggs, Query::hasTargetSRFs, Query::hasWindowFuncs, Query::havingQual, LCS_asString(), LCS_NONE, NIL, and Query::setOperations.

Referenced by preprocess_rowmarks(), and transformLockingClause().

2651 {
2652  Assert(strength != LCS_NONE); /* else caller error */
2653 
2654  if (qry->setOperations)
2655  ereport(ERROR,
2656  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2657  /*------
2658  translator: %s is a SQL row locking clause such as FOR UPDATE */
2659  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
2660  LCS_asString(strength))));
2661  if (qry->distinctClause != NIL)
2662  ereport(ERROR,
2663  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2664  /*------
2665  translator: %s is a SQL row locking clause such as FOR UPDATE */
2666  errmsg("%s is not allowed with DISTINCT clause",
2667  LCS_asString(strength))));
2668  if (qry->groupClause != NIL)
2669  ereport(ERROR,
2670  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2671  /*------
2672  translator: %s is a SQL row locking clause such as FOR UPDATE */
2673  errmsg("%s is not allowed with GROUP BY clause",
2674  LCS_asString(strength))));
2675  if (qry->havingQual != NULL)
2676  ereport(ERROR,
2677  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2678  /*------
2679  translator: %s is a SQL row locking clause such as FOR UPDATE */
2680  errmsg("%s is not allowed with HAVING clause",
2681  LCS_asString(strength))));
2682  if (qry->hasAggs)
2683  ereport(ERROR,
2684  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2685  /*------
2686  translator: %s is a SQL row locking clause such as FOR UPDATE */
2687  errmsg("%s is not allowed with aggregate functions",
2688  LCS_asString(strength))));
2689  if (qry->hasWindowFuncs)
2690  ereport(ERROR,
2691  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2692  /*------
2693  translator: %s is a SQL row locking clause such as FOR UPDATE */
2694  errmsg("%s is not allowed with window functions",
2695  LCS_asString(strength))));
2696  if (qry->hasTargetSRFs)
2697  ereport(ERROR,
2698  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2699  /*------
2700  translator: %s is a SQL row locking clause such as FOR UPDATE */
2701  errmsg("%s is not allowed with set-returning functions in the target list",
2702  LCS_asString(strength))));
2703 }
#define NIL
Definition: pg_list.h:69
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2625
bool hasAggs
Definition: parsenodes.h:123
int errcode(int sqlerrcode)
Definition: elog.c:575
List * distinctClause
Definition: parsenodes.h:154
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool hasTargetSRFs
Definition: parsenodes.h:125
#define Assert(condition)
Definition: c.h:688
bool hasWindowFuncs
Definition: parsenodes.h:124
Node * setOperations
Definition: parsenodes.h:163
List * groupClause
Definition: parsenodes.h:146
int errmsg(const char *fmt,...)
Definition: elog.c:797
Node * havingQual
Definition: parsenodes.h:150

◆ count_rowexpr_columns()

static int count_rowexpr_columns ( ParseState pstate,
Node expr 
)
static

Definition at line 1145 of file analyze.c.

References generate_unaccent_rules::args, TargetEntry::expr, get_tle_by_resno(), GetRTEByRangeTablePosn(), IsA, list_length(), RECORDOID, TargetEntry::resjunk, RTE_SUBQUERY, RangeTblEntry::rtekind, RangeTblEntry::subquery, Query::targetList, Var::varattno, Var::varlevelsup, Var::varno, and Var::vartype.

Referenced by transformInsertRow().

1146 {
1147  if (expr == NULL)
1148  return -1;
1149  if (IsA(expr, RowExpr))
1150  return list_length(((RowExpr *) expr)->args);
1151  if (IsA(expr, Var))
1152  {
1153  Var *var = (Var *) expr;
1154  AttrNumber attnum = var->varattno;
1155 
1156  if (attnum > 0 && var->vartype == RECORDOID)
1157  {
1158  RangeTblEntry *rte;
1159 
1160  rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup);
1161  if (rte->rtekind == RTE_SUBQUERY)
1162  {
1163  /* Subselect-in-FROM: examine sub-select's output expr */
1165  attnum);
1166 
1167  if (ste == NULL || ste->resjunk)
1168  return -1;
1169  expr = (Node *) ste->expr;
1170  if (IsA(expr, RowExpr))
1171  return list_length(((RowExpr *) expr)->args);
1172  }
1173  }
1174  }
1175  return -1;
1176 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
Index varlevelsup
Definition: primnodes.h:173
Definition: nodes.h:513
AttrNumber varattno
Definition: primnodes.h:168
Definition: primnodes.h:163
List * targetList
Definition: parsenodes.h:138
bool resjunk
Definition: primnodes.h:1382
Oid vartype
Definition: primnodes.h:170
#define RECORDOID
Definition: pg_type.h:680
Index varno
Definition: primnodes.h:166
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
Expr * expr
Definition: primnodes.h:1375
static int list_length(const List *l)
Definition: pg_list.h:89
RTEKind rtekind
Definition: parsenodes.h:959
Query * subquery
Definition: parsenodes.h:982
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
int16 AttrNumber
Definition: attnum.h:21

◆ determineRecursiveColTypes()

static void determineRecursiveColTypes ( ParseState pstate,
Node larg,
List nrtargetlist 
)
static

Definition at line 2150 of file analyze.c.

References analyzeCTETargetList(), Assert, TargetEntry::expr, IsA, lappend(), lfirst, list_head(), lnext, makeTargetEntry(), NIL, ParseState::p_parent_cte, ParseState::p_rtable, pstrdup(), TargetEntry::resjunk, TargetEntry::resname, rt_fetch, and Query::targetList.

Referenced by transformSetOperationTree().

2151 {
2152  Node *node;
2153  int leftmostRTI;
2154  Query *leftmostQuery;
2155  List *targetList;
2156  ListCell *left_tlist;
2157  ListCell *nrtl;
2158  int next_resno;
2159 
2160  /*
2161  * Find leftmost leaf SELECT
2162  */
2163  node = larg;
2164  while (node && IsA(node, SetOperationStmt))
2165  node = ((SetOperationStmt *) node)->larg;
2166  Assert(node && IsA(node, RangeTblRef));
2167  leftmostRTI = ((RangeTblRef *) node)->rtindex;
2168  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2169  Assert(leftmostQuery != NULL);
2170 
2171  /*
2172  * Generate dummy targetlist using column names of leftmost select and
2173  * dummy result expressions of the non-recursive term.
2174  */
2175  targetList = NIL;
2176  left_tlist = list_head(leftmostQuery->targetList);
2177  next_resno = 1;
2178 
2179  foreach(nrtl, nrtargetlist)
2180  {
2181  TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
2182  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
2183  char *colName;
2184  TargetEntry *tle;
2185 
2186  Assert(!lefttle->resjunk);
2187  colName = pstrdup(lefttle->resname);
2188  tle = makeTargetEntry(nrtle->expr,
2189  next_resno++,
2190  colName,
2191  false);
2192  targetList = lappend(targetList, tle);
2193  left_tlist = lnext(left_tlist);
2194  }
2195 
2196  /* Now build CTE's output column info using dummy targetlist */
2197  analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
2198 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
void analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
Definition: parse_cte.c:352
char * pstrdup(const char *in)
Definition: mcxt.c:1063
Definition: nodes.h:513
char * resname
Definition: primnodes.h:1377
CommonTableExpr * p_parent_cte
Definition: parse_node.h:183
List * targetList
Definition: parsenodes.h:138
bool resjunk
Definition: primnodes.h:1382
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:237
List * lappend(List *list, void *datum)
Definition: list.c:128
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1375
Definition: pg_list.h:45
List * p_rtable
Definition: parse_node.h:174

◆ LCS_asString()

const char* LCS_asString ( LockClauseStrength  strength)

Definition at line 2625 of file analyze.c.

References Assert, LCS_FORKEYSHARE, LCS_FORNOKEYUPDATE, LCS_FORSHARE, LCS_FORUPDATE, and LCS_NONE.

Referenced by CheckSelectLocking(), grouping_planner(), make_outerjoininfo(), transformDeclareCursorStmt(), transformLockingClause(), transformSetOperationStmt(), transformSetOperationTree(), and transformValuesClause().

2626 {
2627  switch (strength)
2628  {
2629  case LCS_NONE:
2630  Assert(false);
2631  break;
2632  case LCS_FORKEYSHARE:
2633  return "FOR KEY SHARE";
2634  case LCS_FORSHARE:
2635  return "FOR SHARE";
2636  case LCS_FORNOKEYUPDATE:
2637  return "FOR NO KEY UPDATE";
2638  case LCS_FORUPDATE:
2639  return "FOR UPDATE";
2640  }
2641  return "FOR some"; /* shouldn't happen */
2642 }
#define Assert(condition)
Definition: c.h:688

◆ parse_analyze()

Query* parse_analyze ( RawStmt parseTree,
const char *  sourceText,
Oid paramTypes,
int  numParams,
QueryEnvironment queryEnv 
)

Definition at line 100 of file analyze.c.

References Assert, free_parsestate(), make_parsestate(), ParseState::p_queryEnv, ParseState::p_sourcetext, parse_fixed_parameters(), post_parse_analyze_hook, and transformTopLevelStmt().

Referenced by DefineView(), and pg_analyze_and_rewrite().

103 {
104  ParseState *pstate = make_parsestate(NULL);
105  Query *query;
106 
107  Assert(sourceText != NULL); /* required as of 8.4 */
108 
109  pstate->p_sourcetext = sourceText;
110 
111  if (numParams > 0)
112  parse_fixed_parameters(pstate, paramTypes, numParams);
113 
114  pstate->p_queryEnv = queryEnv;
115 
116  query = transformTopLevelStmt(pstate, parseTree);
117 
119  (*post_parse_analyze_hook) (pstate, query);
120 
121  free_parsestate(pstate);
122 
123  return query;
124 }
QueryEnvironment * p_queryEnv
Definition: parse_node.h:197
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
const char * p_sourcetext
Definition: parse_node.h:173
#define Assert(condition)
Definition: c.h:688
void parse_fixed_parameters(ParseState *pstate, Oid *paramTypes, int numParams)
Definition: parse_param.c:67
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:191
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:51

◆ parse_analyze_varparams()

Query* parse_analyze_varparams ( RawStmt parseTree,
const char *  sourceText,
Oid **  paramTypes,
int *  numParams 
)

Definition at line 134 of file analyze.c.

References Assert, check_variable_parameters(), free_parsestate(), make_parsestate(), ParseState::p_sourcetext, parse_variable_parameters(), post_parse_analyze_hook, and transformTopLevelStmt().

Referenced by exec_parse_message(), and PrepareQuery().

136 {
137  ParseState *pstate = make_parsestate(NULL);
138  Query *query;
139 
140  Assert(sourceText != NULL); /* required as of 8.4 */
141 
142  pstate->p_sourcetext = sourceText;
143 
144  parse_variable_parameters(pstate, paramTypes, numParams);
145 
146  query = transformTopLevelStmt(pstate, parseTree);
147 
148  /* make sure all is well with parameter types */
149  check_variable_parameters(pstate, query);
150 
152  (*post_parse_analyze_hook) (pstate, query);
153 
154  free_parsestate(pstate);
155 
156  return query;
157 }
void parse_variable_parameters(ParseState *pstate, Oid **paramTypes, int *numParams)
Definition: parse_param.c:83
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
const char * p_sourcetext
Definition: parse_node.h:173
#define Assert(condition)
Definition: c.h:688
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:191
void check_variable_parameters(ParseState *pstate, Query *query)
Definition: parse_param.c:263
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:51

◆ parse_sub_analyze()

Query* parse_sub_analyze ( Node parseTree,
ParseState parentParseState,
CommonTableExpr parentCTE,
bool  locked_from_parent,
bool  resolve_unknowns 
)

Definition at line 164 of file analyze.c.

References free_parsestate(), make_parsestate(), ParseState::p_locked_from_parent, ParseState::p_parent_cte, ParseState::p_resolve_unknowns, and transformStmt().

Referenced by analyzeCTE(), transformRangeSubselect(), transformSetOperationTree(), and transformSubLink().

168 {
169  ParseState *pstate = make_parsestate(parentParseState);
170  Query *query;
171 
172  pstate->p_parent_cte = parentCTE;
173  pstate->p_locked_from_parent = locked_from_parent;
174  pstate->p_resolve_unknowns = resolve_unknowns;
175 
176  query = transformStmt(pstate, parseTree);
177 
178  free_parsestate(pstate);
179 
180  return query;
181 }
CommonTableExpr * p_parent_cte
Definition: parse_node.h:183
bool p_locked_from_parent
Definition: parse_node.h:192
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
bool p_resolve_unknowns
Definition: parse_node.h:194
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:254
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77

◆ transformCallStmt()

static Query * transformCallStmt ( ParseState pstate,
CallStmt stmt 
)
static

Definition at line 2588 of file analyze.c.

References FuncCall::args, castNode, CMD_UTILITY, Query::commandType, EXPR_KIND_CALL_ARGUMENT, CallStmt::funccall, CallStmt::funcexpr, FuncCall::funcname, lappend(), lfirst, FuncCall::location, makeNode, NIL, ParseState::p_last_srf, ParseFuncOrColumn(), transformExpr(), and Query::utilityStmt.

Referenced by transformStmt().

2589 {
2590  List *targs;
2591  ListCell *lc;
2592  Node *node;
2593  Query *result;
2594 
2595  targs = NIL;
2596  foreach(lc, stmt->funccall->args)
2597  {
2598  targs = lappend(targs, transformExpr(pstate,
2599  (Node *) lfirst(lc),
2601  }
2602 
2603  node = ParseFuncOrColumn(pstate,
2604  stmt->funccall->funcname,
2605  targs,
2606  pstate->p_last_srf,
2607  stmt->funccall,
2608  true,
2609  stmt->funccall->location);
2610 
2611  stmt->funcexpr = castNode(FuncExpr, node);
2612 
2613  result = makeNode(Query);
2614  result->commandType = CMD_UTILITY;
2615  result->utilityStmt = (Node *) stmt;
2616 
2617  return result;
2618 }
#define NIL
Definition: pg_list.h:69
FuncExpr * funcexpr
Definition: parsenodes.h:2818
#define castNode(_type_, nodeptr)
Definition: nodes.h:582
FuncCall * funccall
Definition: parsenodes.h:2817
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:146
Definition: nodes.h:513
int location
Definition: parsenodes.h:358
Node * utilityStmt
Definition: parsenodes.h:118
Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *last_srf, FuncCall *fn, bool proc_call, int location)
Definition: parse_func.c:73
List * lappend(List *list, void *datum)
Definition: list.c:128
Node * p_last_srf
Definition: parse_node.h:206
CmdType commandType
Definition: parsenodes.h:110
#define makeNode(_type_)
Definition: nodes.h:561
#define lfirst(lc)
Definition: pg_list.h:106
List * args
Definition: parsenodes.h:350
List * funcname
Definition: parsenodes.h:349
Definition: pg_list.h:45

◆ transformCreateTableAsStmt()

static Query * transformCreateTableAsStmt ( ParseState pstate,
CreateTableAsStmt stmt 
)
static

Definition at line 2511 of file analyze.c.

References CMD_UTILITY, Query::commandType, copyObject, ereport, errcode(), errmsg(), ERROR, Query::hasModifyingCTE, CreateTableAsStmt::into, isQueryUsingTempRelation(), makeNode, OBJECT_MATVIEW, CreateTableAsStmt::query, query_contains_extern_params(), IntoClause::rel, CreateTableAsStmt::relkind, RangeVar::relpersistence, RELPERSISTENCE_UNLOGGED, transformStmt(), Query::utilityStmt, and IntoClause::viewQuery.

Referenced by transformStmt().

2512 {
2513  Query *result;
2514  Query *query;
2515 
2516  /* transform contained query, not allowing SELECT INTO */
2517  query = transformStmt(pstate, stmt->query);
2518  stmt->query = (Node *) query;
2519 
2520  /* additional work needed for CREATE MATERIALIZED VIEW */
2521  if (stmt->relkind == OBJECT_MATVIEW)
2522  {
2523  /*
2524  * Prohibit a data-modifying CTE in the query used to create a
2525  * materialized view. It's not sufficiently clear what the user would
2526  * want to happen if the MV is refreshed or incrementally maintained.
2527  */
2528  if (query->hasModifyingCTE)
2529  ereport(ERROR,
2530  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2531  errmsg("materialized views must not use data-modifying statements in WITH")));
2532 
2533  /*
2534  * Check whether any temporary database objects are used in the
2535  * creation query. It would be hard to refresh data or incrementally
2536  * maintain it if a source disappeared.
2537  */
2538  if (isQueryUsingTempRelation(query))
2539  ereport(ERROR,
2540  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2541  errmsg("materialized views must not use temporary tables or views")));
2542 
2543  /*
2544  * A materialized view would either need to save parameters for use in
2545  * maintaining/loading the data or prohibit them entirely. The latter
2546  * seems safer and more sane.
2547  */
2548  if (query_contains_extern_params(query))
2549  ereport(ERROR,
2550  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2551  errmsg("materialized views may not be defined using bound parameters")));
2552 
2553  /*
2554  * For now, we disallow unlogged materialized views, because it seems
2555  * like a bad idea for them to just go to empty after a crash. (If we
2556  * could mark them as unpopulated, that would be better, but that
2557  * requires catalog changes which crash recovery can't presently
2558  * handle.)
2559  */
2561  ereport(ERROR,
2562  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2563  errmsg("materialized views cannot be UNLOGGED")));
2564 
2565  /*
2566  * At runtime, we'll need a copy of the parsed-but-not-rewritten Query
2567  * for purposes of creating the view's ON SELECT rule. We stash that
2568  * in the IntoClause because that's where intorel_startup() can
2569  * conveniently get it from.
2570  */
2571  stmt->into->viewQuery = (Node *) copyObject(query);
2572  }
2573 
2574  /* represent the command as a utility Query */
2575  result = makeNode(Query);
2576  result->commandType = CMD_UTILITY;
2577  result->utilityStmt = (Node *) stmt;
2578 
2579  return result;
2580 }
bool isQueryUsingTempRelation(Query *query)
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:172
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
Node * utilityStmt
Definition: parsenodes.h:118
#define ERROR
Definition: elog.h:43
Node * viewQuery
Definition: primnodes.h:114
ObjectType relkind
Definition: parsenodes.h:3188
#define ereport(elevel, rest)
Definition: elog.h:122
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:254
IntoClause * into
Definition: parsenodes.h:3187
CmdType commandType
Definition: parsenodes.h:110
#define makeNode(_type_)
Definition: nodes.h:561
bool query_contains_extern_params(Query *query)
Definition: parse_param.c:325
char relpersistence
Definition: primnodes.h:71
int errmsg(const char *fmt,...)
Definition: elog.c:797
RangeVar * rel
Definition: primnodes.h:109
bool hasModifyingCTE
Definition: parsenodes.h:129
#define copyObject(obj)
Definition: nodes.h:626

◆ transformDeclareCursorStmt()

static Query * transformDeclareCursorStmt ( ParseState pstate,
DeclareCursorStmt stmt 
)
static

Definition at line 2401 of file analyze.c.

References CMD_SELECT, CMD_UTILITY, Query::commandType, CURSOR_OPT_HOLD, CURSOR_OPT_INSENSITIVE, CURSOR_OPT_NO_SCROLL, CURSOR_OPT_SCROLL, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, Query::hasModifyingCTE, IsA, LCS_asString(), linitial, makeNode, NIL, DeclareCursorStmt::options, DeclareCursorStmt::query, Query::rowMarks, transformStmt(), and Query::utilityStmt.

Referenced by transformStmt().

2402 {
2403  Query *result;
2404  Query *query;
2405 
2406  /*
2407  * Don't allow both SCROLL and NO SCROLL to be specified
2408  */
2409  if ((stmt->options & CURSOR_OPT_SCROLL) &&
2410  (stmt->options & CURSOR_OPT_NO_SCROLL))
2411  ereport(ERROR,
2412  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2413  errmsg("cannot specify both SCROLL and NO SCROLL")));
2414 
2415  /* Transform contained query, not allowing SELECT INTO */
2416  query = transformStmt(pstate, stmt->query);
2417  stmt->query = (Node *) query;
2418 
2419  /* Grammar should not have allowed anything but SELECT */
2420  if (!IsA(query, Query) ||
2421  query->commandType != CMD_SELECT)
2422  elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR");
2423 
2424  /*
2425  * We also disallow data-modifying WITH in a cursor. (This could be
2426  * allowed, but the semantics of when the updates occur might be
2427  * surprising.)
2428  */
2429  if (query->hasModifyingCTE)
2430  ereport(ERROR,
2431  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2432  errmsg("DECLARE CURSOR must not contain data-modifying statements in WITH")));
2433 
2434  /* FOR UPDATE and WITH HOLD are not compatible */
2435  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
2436  ereport(ERROR,
2437  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2438  /*------
2439  translator: %s is a SQL row locking clause such as FOR UPDATE */
2440  errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
2442  linitial(query->rowMarks))->strength)),
2443  errdetail("Holdable cursors must be READ ONLY.")));
2444 
2445  /* FOR UPDATE and SCROLL are not compatible */
2446  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
2447  ereport(ERROR,
2448  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2449  /*------
2450  translator: %s is a SQL row locking clause such as FOR UPDATE */
2451  errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
2453  linitial(query->rowMarks))->strength)),
2454  errdetail("Scrollable cursors must be READ ONLY.")));
2455 
2456  /* FOR UPDATE and INSENSITIVE are not compatible */
2457  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
2458  ereport(ERROR,
2459  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2460  /*------
2461  translator: %s is a SQL row locking clause such as FOR UPDATE */
2462  errmsg("DECLARE INSENSITIVE CURSOR ... %s is not supported",
2464  linitial(query->rowMarks))->strength)),
2465  errdetail("Insensitive cursors must be READ ONLY.")));
2466 
2467  /* represent the command as a utility Query */
2468  result = makeNode(Query);
2469  result->commandType = CMD_UTILITY;
2470  result->utilityStmt = (Node *) stmt;
2471 
2472  return result;
2473 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2625
#define CURSOR_OPT_HOLD
Definition: parsenodes.h:2642
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
#define CURSOR_OPT_INSENSITIVE
Definition: parsenodes.h:2641
List * rowMarks
Definition: parsenodes.h:161
Node * utilityStmt
Definition: parsenodes.h:118
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:2640
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:254
CmdType commandType
Definition: parsenodes.h:110
#define makeNode(_type_)
Definition: nodes.h:561
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2639
bool hasModifyingCTE
Definition: parsenodes.h:129
#define elog
Definition: elog.h:219

◆ transformDeleteStmt()

static Query * transformDeleteStmt ( ParseState pstate,
DeleteStmt stmt 
)
static

Definition at line 396 of file analyze.c.

References ACL_DELETE, assign_query_collations(), CMD_DELETE, Query::commandType, Query::cteList, Query::distinctClause, EXPR_KIND_WHERE, Query::hasAggs, Query::hasModifyingCTE, Query::hasRecursive, Query::hasSubLinks, Query::hasTargetSRFs, Query::hasWindowFuncs, RangeVar::inh, Query::jointree, llast, makeFromExpr(), makeNode, NIL, ParseState::p_hasAggs, ParseState::p_hasModifyingCTE, ParseState::p_hasSubLinks, ParseState::p_hasTargetSRFs, ParseState::p_hasWindowFuncs, ParseState::p_joinlist, ParseNamespaceItem::p_lateral_ok, ParseNamespaceItem::p_lateral_only, ParseState::p_namespace, ParseState::p_rtable, parseCheckAggregates(), WithClause::recursive, DeleteStmt::relation, Query::resultRelation, Query::returningList, DeleteStmt::returningList, Query::rtable, setTargetTable(), transformFromClause(), transformReturningList(), transformWhereClause(), transformWithClause(), DeleteStmt::usingClause, DeleteStmt::whereClause, and DeleteStmt::withClause.

Referenced by transformStmt().

397 {
398  Query *qry = makeNode(Query);
399  ParseNamespaceItem *nsitem;
400  Node *qual;
401 
402  qry->commandType = CMD_DELETE;
403 
404  /* process the WITH clause independently of all else */
405  if (stmt->withClause)
406  {
407  qry->hasRecursive = stmt->withClause->recursive;
408  qry->cteList = transformWithClause(pstate, stmt->withClause);
409  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
410  }
411 
412  /* set up range table with just the result rel */
413  qry->resultRelation = setTargetTable(pstate, stmt->relation,
414  stmt->relation->inh,
415  true,
416  ACL_DELETE);
417 
418  /* grab the namespace item made by setTargetTable */
419  nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
420 
421  /* there's no DISTINCT in DELETE */
422  qry->distinctClause = NIL;
423 
424  /* subqueries in USING cannot access the result relation */
425  nsitem->p_lateral_only = true;
426  nsitem->p_lateral_ok = false;
427 
428  /*
429  * The USING clause is non-standard SQL syntax, and is equivalent in
430  * functionality to the FROM list that can be specified for UPDATE. The
431  * USING keyword is used rather than FROM because FROM is already a
432  * keyword in the DELETE syntax.
433  */
434  transformFromClause(pstate, stmt->usingClause);
435 
436  /* remaining clauses can reference the result relation normally */
437  nsitem->p_lateral_only = false;
438  nsitem->p_lateral_ok = true;
439 
440  qual = transformWhereClause(pstate, stmt->whereClause,
441  EXPR_KIND_WHERE, "WHERE");
442 
443  qry->returningList = transformReturningList(pstate, stmt->returningList);
444 
445  /* done building the range table and jointree */
446  qry->rtable = pstate->p_rtable;
447  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
448 
449  qry->hasSubLinks = pstate->p_hasSubLinks;
450  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
451  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
452  qry->hasAggs = pstate->p_hasAggs;
453  if (pstate->p_hasAggs)
454  parseCheckAggregates(pstate, qry);
455 
456  assign_query_collations(pstate, qry);
457 
458  return qry;
459 }
#define NIL
Definition: pg_list.h:69
bool p_hasSubLinks
Definition: parse_node.h:203
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:284
RangeVar * relation
Definition: parsenodes.h:1483
FromExpr * jointree
Definition: parsenodes.h:136
bool hasAggs
Definition: parsenodes.h:123
int resultRelation
Definition: parsenodes.h:120
#define llast(l)
Definition: pg_list.h:131
bool p_hasTargetSRFs
Definition: parse_node.h:202
Definition: nodes.h:513
#define ACL_DELETE
Definition: parsenodes.h:75
bool p_hasAggs
Definition: parse_node.h:200
static List * transformReturningList(ParseState *pstate, List *returningList)
Definition: analyze.c:2344
void parseCheckAggregates(ParseState *pstate, Query *qry)
Definition: parse_agg.c:1011
bool p_hasWindowFuncs
Definition: parse_node.h:201
bool hasRecursive
Definition: parsenodes.h:128
WithClause * withClause
Definition: parsenodes.h:1487
List * returningList
Definition: parsenodes.h:1486
List * rtable
Definition: parsenodes.h:135
List * distinctClause
Definition: parsenodes.h:154
List * p_namespace
Definition: parse_node.h:178
bool recursive
Definition: parsenodes.h:1346
List * returningList
Definition: parsenodes.h:144
bool p_hasModifyingCTE
Definition: parse_node.h:204
bool inh
Definition: primnodes.h:69
void transformFromClause(ParseState *pstate, List *frmList)
Definition: parse_clause.c:119
Node * whereClause
Definition: parsenodes.h:1485
List * usingClause
Definition: parsenodes.h:1484
int setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource, AclMode requiredPerms)
Definition: parse_clause.c:185
CmdType commandType
Definition: parsenodes.h:110
bool hasTargetSRFs
Definition: parsenodes.h:125
#define makeNode(_type_)
Definition: nodes.h:561
bool hasWindowFuncs
Definition: parsenodes.h:124
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
List * cteList
Definition: parsenodes.h:133
bool hasSubLinks
Definition: parsenodes.h:126
void assign_query_collations(ParseState *pstate, Query *query)
List * p_joinlist
Definition: parse_node.h:176
bool hasModifyingCTE
Definition: parsenodes.h:129
List * p_rtable
Definition: parse_node.h:174

◆ transformExplainStmt()

static Query * transformExplainStmt ( ParseState pstate,
ExplainStmt stmt 
)
static

Definition at line 2487 of file analyze.c.

References CMD_UTILITY, Query::commandType, makeNode, ExplainStmt::query, transformOptionalSelectInto(), and Query::utilityStmt.

Referenced by transformStmt().

2488 {
2489  Query *result;
2490 
2491  /* transform contained query, allowing SELECT INTO */
2492  stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
2493 
2494  /* represent the command as a utility Query */
2495  result = makeNode(Query);
2496  result->commandType = CMD_UTILITY;
2497  result->utilityStmt = (Node *) stmt;
2498 
2499  return result;
2500 }
Definition: nodes.h:513
Node * utilityStmt
Definition: parsenodes.h:118
Node * query
Definition: parsenodes.h:3166
CmdType commandType
Definition: parsenodes.h:110
#define makeNode(_type_)
Definition: nodes.h:561
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:215

◆ transformInsertRow()

static List * transformInsertRow ( ParseState pstate,
List exprlist,
List stmtcols,
List icolumns,
List attrnos,
bool  strip_indirection 
)
static

Definition at line 899 of file analyze.c.

References count_rowexpr_columns(), ereport, errcode(), errhint(), errmsg(), ERROR, EXPR_KIND_INSERT_TARGET, exprLocation(), ResTarget::indirection, IsA, lappend(), lfirst, lfirst_int, lfirst_node, linitial, list_head(), list_length(), list_nth(), lnext, ResTarget::location, ResTarget::name, FieldStore::newvals, NIL, parser_errposition(), ArrayRef::refassgnexpr, and transformAssignedExpr().

Referenced by transformInsertStmt().

902 {
903  List *result;
904  ListCell *lc;
905  ListCell *icols;
906  ListCell *attnos;
907 
908  /*
909  * Check length of expr list. It must not have more expressions than
910  * there are target columns. We allow fewer, but only if no explicit
911  * columns list was given (the remaining columns are implicitly
912  * defaulted). Note we must check this *after* transformation because
913  * that could expand '*' into multiple items.
914  */
915  if (list_length(exprlist) > list_length(icolumns))
916  ereport(ERROR,
917  (errcode(ERRCODE_SYNTAX_ERROR),
918  errmsg("INSERT has more expressions than target columns"),
919  parser_errposition(pstate,
920  exprLocation(list_nth(exprlist,
921  list_length(icolumns))))));
922  if (stmtcols != NIL &&
923  list_length(exprlist) < list_length(icolumns))
924  {
925  /*
926  * We can get here for cases like INSERT ... SELECT (a,b,c) FROM ...
927  * where the user accidentally created a RowExpr instead of separate
928  * columns. Add a suitable hint if that seems to be the problem,
929  * because the main error message is quite misleading for this case.
930  * (If there's no stmtcols, you'll get something about data type
931  * mismatch, which is less misleading so we don't worry about giving a
932  * hint in that case.)
933  */
934  ereport(ERROR,
935  (errcode(ERRCODE_SYNTAX_ERROR),
936  errmsg("INSERT has more target columns than expressions"),
937  ((list_length(exprlist) == 1 &&
938  count_rowexpr_columns(pstate, linitial(exprlist)) ==
939  list_length(icolumns)) ?
940  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),
941  parser_errposition(pstate,
942  exprLocation(list_nth(icolumns,
943  list_length(exprlist))))));
944  }
945 
946  /*
947  * Prepare columns for assignment to target table.
948  */
949  result = NIL;
950  icols = list_head(icolumns);
951  attnos = list_head(attrnos);
952  foreach(lc, exprlist)
953  {
954  Expr *expr = (Expr *) lfirst(lc);
955  ResTarget *col;
956 
957  col = lfirst_node(ResTarget, icols);
958 
959  expr = transformAssignedExpr(pstate, expr,
961  col->name,
962  lfirst_int(attnos),
963  col->indirection,
964  col->location);
965 
966  if (strip_indirection)
967  {
968  while (expr)
969  {
970  if (IsA(expr, FieldStore))
971  {
972  FieldStore *fstore = (FieldStore *) expr;
973 
974  expr = (Expr *) linitial(fstore->newvals);
975  }
976  else if (IsA(expr, ArrayRef))
977  {
978  ArrayRef *aref = (ArrayRef *) expr;
979 
980  if (aref->refassgnexpr == NULL)
981  break;
982  expr = aref->refassgnexpr;
983  }
984  else
985  break;
986  }
987  }
988 
989  result = lappend(result, expr);
990 
991  icols = lnext(icols);
992  attnos = lnext(attnos);
993  }
994 
995  return result;
996 }
List * indirection
Definition: parsenodes.h:440
#define NIL
Definition: pg_list.h:69
Expr * refassgnexpr
Definition: primnodes.h:410
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
int errhint(const char *fmt,...)
Definition: elog.c:987
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1186
Expr * transformAssignedExpr(ParseState *pstate, Expr *expr, ParseExprKind exprKind, const char *colname, int attrno, List *indirection, int location)
Definition: parse_target.c:455
char * name
Definition: parsenodes.h:439
static int count_rowexpr_columns(ParseState *pstate, Node *expr)
Definition: analyze.c:1145
int errcode(int sqlerrcode)
Definition: elog.c:575
int location
Definition: parsenodes.h:442
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:107
#define lfirst_node(type, lc)
Definition: pg_list.h:109
void * list_nth(const List *list, int n)
Definition: list.c:410
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
List * newvals
Definition: primnodes.h:772
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: pg_list.h:45

◆ transformInsertStmt()

static Query * transformInsertStmt ( ParseState pstate,
InsertStmt stmt 
)
static

Definition at line 466 of file analyze.c.

References ACL_INSERT, ACL_UPDATE, OnConflictClause::action, addRangeTableEntryForSubquery(), addRangeTableEntryForValues(), addRTEtoQuery(), Assert, assign_list_collations(), assign_query_collations(), bms_add_member(), checkInsertTargets(), CMD_INSERT, CMD_SELECT, InsertStmt::cols, Query::commandType, contain_vars_of_level(), Query::cteList, elog, ereport, errcode(), errmsg(), ERROR, expandRTE(), TargetEntry::expr, EXPR_KIND_VALUES, EXPR_KIND_VALUES_SINGLE, exprLocation(), exprType(), exprTypmod(), FirstLowInvalidHeapAttributeNumber, free_parsestate(), Query::hasModifyingCTE, Query::hasRecursive, InvalidOid, IsA, lappend(), lappend_int(), lappend_oid(), lfirst, lfirst_int, lfirst_node, SelectStmt::limitCount, SelectStmt::limitOffset, linitial, list_head(), list_length(), lnext, Var::location, SelectStmt::lockingClause, make_parsestate(), makeAlias(), makeFromExpr(), makeNode, makeTargetEntry(), makeVarFromTargetEntry(), ResTarget::name, NIL, ONCONFLICT_UPDATE, InsertStmt::onConflictClause, Query::override, InsertStmt::override, ParseState::p_ctenamespace, ParseState::p_hasModifyingCTE, ParseState::p_is_insert, ParseState::p_joinexprs, ParseState::p_joinlist, ParseState::p_namespace, ParseState::p_resolve_unknowns, ParseState::p_rtable, parser_errposition(), WithClause::recursive, InsertStmt::relation, TargetEntry::resjunk, Query::resultRelation, rt_fetch, InsertStmt::selectStmt, setTargetTable(), SelectStmt::sortClause, Query::targetList, transformExpressionList(), transformInsertRow(), transformOnConflictClause(), transformReturningList(), transformStmt(), transformWithClause(), UNKNOWNOID, val, SelectStmt::valuesLists, InsertStmt::withClause, and SelectStmt::withClause.

Referenced by transformStmt().

467 {
468  Query *qry = makeNode(Query);
469  SelectStmt *selectStmt = (SelectStmt *) stmt->selectStmt;
470  List *exprList = NIL;
471  bool isGeneralSelect;
472  List *sub_rtable;
473  List *sub_namespace;
474  List *icolumns;
475  List *attrnos;
476  RangeTblEntry *rte;
477  RangeTblRef *rtr;
478  ListCell *icols;
479  ListCell *attnos;
480  ListCell *lc;
481  bool isOnConflictUpdate;
482  AclMode targetPerms;
483 
484  /* There can't be any outer WITH to worry about */
485  Assert(pstate->p_ctenamespace == NIL);
486 
487  qry->commandType = CMD_INSERT;
488  pstate->p_is_insert = true;
489 
490  /* process the WITH clause independently of all else */
491  if (stmt->withClause)
492  {
493  qry->hasRecursive = stmt->withClause->recursive;
494  qry->cteList = transformWithClause(pstate, stmt->withClause);
495  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
496  }
497 
498  qry->override = stmt->override;
499 
500  isOnConflictUpdate = (stmt->onConflictClause &&
502 
503  /*
504  * We have three cases to deal with: DEFAULT VALUES (selectStmt == NULL),
505  * VALUES list, or general SELECT input. We special-case VALUES, both for
506  * efficiency and so we can handle DEFAULT specifications.
507  *
508  * The grammar allows attaching ORDER BY, LIMIT, FOR UPDATE, or WITH to a
509  * VALUES clause. If we have any of those, treat it as a general SELECT;
510  * so it will work, but you can't use DEFAULT items together with those.
511  */
512  isGeneralSelect = (selectStmt && (selectStmt->valuesLists == NIL ||
513  selectStmt->sortClause != NIL ||
514  selectStmt->limitOffset != NULL ||
515  selectStmt->limitCount != NULL ||
516  selectStmt->lockingClause != NIL ||
517  selectStmt->withClause != NULL));
518 
519  /*
520  * If a non-nil rangetable/namespace was passed in, and we are doing
521  * INSERT/SELECT, arrange to pass the rangetable/namespace down to the
522  * SELECT. This can only happen if we are inside a CREATE RULE, and in
523  * that case we want the rule's OLD and NEW rtable entries to appear as
524  * part of the SELECT's rtable, not as outer references for it. (Kluge!)
525  * The SELECT's joinlist is not affected however. We must do this before
526  * adding the target table to the INSERT's rtable.
527  */
528  if (isGeneralSelect)
529  {
530  sub_rtable = pstate->p_rtable;
531  pstate->p_rtable = NIL;
532  sub_namespace = pstate->p_namespace;
533  pstate->p_namespace = NIL;
534  }
535  else
536  {
537  sub_rtable = NIL; /* not used, but keep compiler quiet */
538  sub_namespace = NIL;
539  }
540 
541  /*
542  * Must get write lock on INSERT target table before scanning SELECT, else
543  * we will grab the wrong kind of initial lock if the target table is also
544  * mentioned in the SELECT part. Note that the target table is not added
545  * to the joinlist or namespace.
546  */
547  targetPerms = ACL_INSERT;
548  if (isOnConflictUpdate)
549  targetPerms |= ACL_UPDATE;
550  qry->resultRelation = setTargetTable(pstate, stmt->relation,
551  false, false, targetPerms);
552 
553  /* Validate stmt->cols list, or build default list if no list given */
554  icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
555  Assert(list_length(icolumns) == list_length(attrnos));
556 
557  /*
558  * Determine which variant of INSERT we have.
559  */
560  if (selectStmt == NULL)
561  {
562  /*
563  * We have INSERT ... DEFAULT VALUES. We can handle this case by
564  * emitting an empty targetlist --- all columns will be defaulted when
565  * the planner expands the targetlist.
566  */
567  exprList = NIL;
568  }
569  else if (isGeneralSelect)
570  {
571  /*
572  * We make the sub-pstate a child of the outer pstate so that it can
573  * see any Param definitions supplied from above. Since the outer
574  * pstate's rtable and namespace are presently empty, there are no
575  * side-effects of exposing names the sub-SELECT shouldn't be able to
576  * see.
577  */
578  ParseState *sub_pstate = make_parsestate(pstate);
579  Query *selectQuery;
580 
581  /*
582  * Process the source SELECT.
583  *
584  * It is important that this be handled just like a standalone SELECT;
585  * otherwise the behavior of SELECT within INSERT might be different
586  * from a stand-alone SELECT. (Indeed, Postgres up through 6.5 had
587  * bugs of just that nature...)
588  *
589  * The sole exception is that we prevent resolving unknown-type
590  * outputs as TEXT. This does not change the semantics since if the
591  * column type matters semantically, it would have been resolved to
592  * something else anyway. Doing this lets us resolve such outputs as
593  * the target column's type, which we handle below.
594  */
595  sub_pstate->p_rtable = sub_rtable;
596  sub_pstate->p_joinexprs = NIL; /* sub_rtable has no joins */
597  sub_pstate->p_namespace = sub_namespace;
598  sub_pstate->p_resolve_unknowns = false;
599 
600  selectQuery = transformStmt(sub_pstate, stmt->selectStmt);
601 
602  free_parsestate(sub_pstate);
603 
604  /* The grammar should have produced a SELECT */
605  if (!IsA(selectQuery, Query) ||
606  selectQuery->commandType != CMD_SELECT)
607  elog(ERROR, "unexpected non-SELECT command in INSERT ... SELECT");
608 
609  /*
610  * Make the source be a subquery in the INSERT's rangetable, and add
611  * it to the INSERT's joinlist.
612  */
613  rte = addRangeTableEntryForSubquery(pstate,
614  selectQuery,
615  makeAlias("*SELECT*", NIL),
616  false,
617  false);
618  rtr = makeNode(RangeTblRef);
619  /* assume new rte is at end */
620  rtr->rtindex = list_length(pstate->p_rtable);
621  Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
622  pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
623 
624  /*----------
625  * Generate an expression list for the INSERT that selects all the
626  * non-resjunk columns from the subquery. (INSERT's tlist must be
627  * separate from the subquery's tlist because we may add columns,
628  * insert datatype coercions, etc.)
629  *
630  * HACK: unknown-type constants and params in the SELECT's targetlist
631  * are copied up as-is rather than being referenced as subquery
632  * outputs. This is to ensure that when we try to coerce them to
633  * the target column's datatype, the right things happen (see
634  * special cases in coerce_type). Otherwise, this fails:
635  * INSERT INTO foo SELECT 'bar', ... FROM baz
636  *----------
637  */
638  exprList = NIL;
639  foreach(lc, selectQuery->targetList)
640  {
641  TargetEntry *tle = (TargetEntry *) lfirst(lc);
642  Expr *expr;
643 
644  if (tle->resjunk)
645  continue;
646  if (tle->expr &&
647  (IsA(tle->expr, Const) ||IsA(tle->expr, Param)) &&
648  exprType((Node *) tle->expr) == UNKNOWNOID)
649  expr = tle->expr;
650  else
651  {
652  Var *var = makeVarFromTargetEntry(rtr->rtindex, tle);
653 
654  var->location = exprLocation((Node *) tle->expr);
655  expr = (Expr *) var;
656  }
657  exprList = lappend(exprList, expr);
658  }
659 
660  /* Prepare row for assignment to target table */
661  exprList = transformInsertRow(pstate, exprList,
662  stmt->cols,
663  icolumns, attrnos,
664  false);
665  }
666  else if (list_length(selectStmt->valuesLists) > 1)
667  {
668  /*
669  * Process INSERT ... VALUES with multiple VALUES sublists. We
670  * generate a VALUES RTE holding the transformed expression lists, and
671  * build up a targetlist containing Vars that reference the VALUES
672  * RTE.
673  */
674  List *exprsLists = NIL;
675  List *coltypes = NIL;
676  List *coltypmods = NIL;
677  List *colcollations = NIL;
678  int sublist_length = -1;
679  bool lateral = false;
680 
681  Assert(selectStmt->intoClause == NULL);
682 
683  foreach(lc, selectStmt->valuesLists)
684  {
685  List *sublist = (List *) lfirst(lc);
686 
687  /*
688  * Do basic expression transformation (same as a ROW() expr, but
689  * allow SetToDefault at top level)
690  */
691  sublist = transformExpressionList(pstate, sublist,
692  EXPR_KIND_VALUES, true);
693 
694  /*
695  * All the sublists must be the same length, *after*
696  * transformation (which might expand '*' into multiple items).
697  * The VALUES RTE can't handle anything different.
698  */
699  if (sublist_length < 0)
700  {
701  /* Remember post-transformation length of first sublist */
702  sublist_length = list_length(sublist);
703  }
704  else if (sublist_length != list_length(sublist))
705  {
706  ereport(ERROR,
707  (errcode(ERRCODE_SYNTAX_ERROR),
708  errmsg("VALUES lists must all be the same length"),
709  parser_errposition(pstate,
710  exprLocation((Node *) sublist))));
711  }
712 
713  /*
714  * Prepare row for assignment to target table. We process any
715  * indirection on the target column specs normally but then strip
716  * off the resulting field/array assignment nodes, since we don't
717  * want the parsed statement to contain copies of those in each
718  * VALUES row. (It's annoying to have to transform the
719  * indirection specs over and over like this, but avoiding it
720  * would take some really messy refactoring of
721  * transformAssignmentIndirection.)
722  */
723  sublist = transformInsertRow(pstate, sublist,
724  stmt->cols,
725  icolumns, attrnos,
726  true);
727 
728  /*
729  * We must assign collations now because assign_query_collations
730  * doesn't process rangetable entries. We just assign all the
731  * collations independently in each row, and don't worry about
732  * whether they are consistent vertically. The outer INSERT query
733  * isn't going to care about the collations of the VALUES columns,
734  * so it's not worth the effort to identify a common collation for
735  * each one here. (But note this does have one user-visible
736  * consequence: INSERT ... VALUES won't complain about conflicting
737  * explicit COLLATEs in a column, whereas the same VALUES
738  * construct in another context would complain.)
739  */
740  assign_list_collations(pstate, sublist);
741 
742  exprsLists = lappend(exprsLists, sublist);
743  }
744 
745  /*
746  * Construct column type/typmod/collation lists for the VALUES RTE.
747  * Every expression in each column has been coerced to the type/typmod
748  * of the corresponding target column or subfield, so it's sufficient
749  * to look at the exprType/exprTypmod of the first row. We don't care
750  * about the collation labeling, so just fill in InvalidOid for that.
751  */
752  foreach(lc, (List *) linitial(exprsLists))
753  {
754  Node *val = (Node *) lfirst(lc);
755 
756  coltypes = lappend_oid(coltypes, exprType(val));
757  coltypmods = lappend_int(coltypmods, exprTypmod(val));
758  colcollations = lappend_oid(colcollations, InvalidOid);
759  }
760 
761  /*
762  * Ordinarily there can't be any current-level Vars in the expression
763  * lists, because the namespace was empty ... but if we're inside
764  * CREATE RULE, then NEW/OLD references might appear. In that case we
765  * have to mark the VALUES RTE as LATERAL.
766  */
767  if (list_length(pstate->p_rtable) != 1 &&
768  contain_vars_of_level((Node *) exprsLists, 0))
769  lateral = true;
770 
771  /*
772  * Generate the VALUES RTE
773  */
774  rte = addRangeTableEntryForValues(pstate, exprsLists,
775  coltypes, coltypmods, colcollations,
776  NULL, lateral, true);
777  rtr = makeNode(RangeTblRef);
778  /* assume new rte is at end */
779  rtr->rtindex = list_length(pstate->p_rtable);
780  Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
781  pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
782 
783  /*
784  * Generate list of Vars referencing the RTE
785  */
786  expandRTE(rte, rtr->rtindex, 0, -1, false, NULL, &exprList);
787 
788  /*
789  * Re-apply any indirection on the target column specs to the Vars
790  */
791  exprList = transformInsertRow(pstate, exprList,
792  stmt->cols,
793  icolumns, attrnos,
794  false);
795  }
796  else
797  {
798  /*
799  * Process INSERT ... VALUES with a single VALUES sublist. We treat
800  * this case separately for efficiency. The sublist is just computed
801  * directly as the Query's targetlist, with no VALUES RTE. So it
802  * works just like a SELECT without any FROM.
803  */
804  List *valuesLists = selectStmt->valuesLists;
805 
806  Assert(list_length(valuesLists) == 1);
807  Assert(selectStmt->intoClause == NULL);
808 
809  /*
810  * Do basic expression transformation (same as a ROW() expr, but allow
811  * SetToDefault at top level)
812  */
813  exprList = transformExpressionList(pstate,
814  (List *) linitial(valuesLists),
816  true);
817 
818  /* Prepare row for assignment to target table */
819  exprList = transformInsertRow(pstate, exprList,
820  stmt->cols,
821  icolumns, attrnos,
822  false);
823  }
824 
825  /*
826  * Generate query's target list using the computed list of expressions.
827  * Also, mark all the target columns as needing insert permissions.
828  */
829  rte = pstate->p_target_rangetblentry;
830  qry->targetList = NIL;
831  icols = list_head(icolumns);
832  attnos = list_head(attrnos);
833  foreach(lc, exprList)
834  {
835  Expr *expr = (Expr *) lfirst(lc);
836  ResTarget *col;
837  AttrNumber attr_num;
838  TargetEntry *tle;
839 
840  col = lfirst_node(ResTarget, icols);
841  attr_num = (AttrNumber) lfirst_int(attnos);
842 
843  tle = makeTargetEntry(expr,
844  attr_num,
845  col->name,
846  false);
847  qry->targetList = lappend(qry->targetList, tle);
848 
849  rte->insertedCols = bms_add_member(rte->insertedCols,
851 
852  icols = lnext(icols);
853  attnos = lnext(attnos);
854  }
855 
856  /* Process ON CONFLICT, if any. */
857  if (stmt->onConflictClause)
859  stmt->onConflictClause);
860 
861  /*
862  * If we have a RETURNING clause, we need to add the target relation to
863  * the query namespace before processing it, so that Var references in
864  * RETURNING will work. Also, remove any namespace entries added in a
865  * sub-SELECT or VALUES list.
866  */
867  if (stmt->returningList)
868  {
869  pstate->p_namespace = NIL;
870  addRTEtoQuery(pstate, pstate->p_target_rangetblentry,
871  false, true, true);
873  stmt->returningList);
874  }
875 
876  /* done building the range table and jointree */
877  qry->rtable = pstate->p_rtable;
878  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
879 
880  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
881  qry->hasSubLinks = pstate->p_hasSubLinks;
882 
883  assign_query_collations(pstate, qry);
884 
885  return qry;
886 }
#define NIL
Definition: pg_list.h:69
bool p_hasSubLinks
Definition: parse_node.h:203
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:284
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
IntoClause * intoClause
Definition: parsenodes.h:1535
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1186
FromExpr * jointree
Definition: parsenodes.h:136
char * name
Definition: parsenodes.h:439
OnConflictExpr * onConflict
Definition: parsenodes.h:142
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
Node * limitOffset
Definition: parsenodes.h:1558
int resultRelation
Definition: parsenodes.h:120
Var * makeVarFromTargetEntry(Index varno, TargetEntry *tle)
Definition: makefuncs.c:104
bool p_hasTargetSRFs
Definition: parse_node.h:202
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
static List * transformReturningList(ParseState *pstate, List *returningList)
Definition: analyze.c:2344
Definition: primnodes.h:163
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
WithClause * withClause
Definition: parsenodes.h:1472
OnConflictClause * onConflictClause
Definition: parsenodes.h:1470
List * targetList
Definition: parsenodes.h:138
bool hasRecursive
Definition: parsenodes.h:128
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:386
uint32 AclMode
Definition: parsenodes.h:70
bool resjunk
Definition: primnodes.h:1382
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:107
Node * selectStmt
Definition: parsenodes.h:1469
bool p_resolve_unknowns
Definition: parse_node.h:194
List * cols
Definition: parsenodes.h:1468
#define lfirst_node(type, lc)
Definition: pg_list.h:109
int location
Definition: primnodes.h:178
void assign_list_collations(ParseState *pstate, List *exprs)
List * p_namespace
Definition: parse_node.h:178
List * sortClause
Definition: parsenodes.h:1557
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
bool recursive
Definition: parsenodes.h:1346
List * valuesLists
Definition: parsenodes.h:1551
List * returningList
Definition: parsenodes.h:144
List * returningList
Definition: parsenodes.h:1471
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:237
List * lockingClause
Definition: parsenodes.h:1560
bool p_hasModifyingCTE
Definition: parse_node.h:204
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
List * lappend_int(List *list, int datum)
Definition: list.c:146
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:254
List * lappend(List *list, void *datum)
Definition: list.c:128
RangeTblEntry * addRangeTableEntryForSubquery(ParseState *pstate, Query *subquery, Alias *alias, bool lateral, bool inFromCl)
void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, int location, bool include_dropped, List **colnames, List **colvars)
OverridingKind override
Definition: parsenodes.h:1473
#define ACL_UPDATE
Definition: parsenodes.h:74
List * transformExpressionList(ParseState *pstate, List *exprlist, ParseExprKind exprKind, bool allowDefault)
Definition: parse_target.c:228
OverridingKind override
Definition: parsenodes.h:140
RangeVar * relation
Definition: parsenodes.h:1467
RangeTblEntry * p_target_rangetblentry
Definition: parse_node.h:185
#define InvalidOid
Definition: postgres_ext.h:36
int setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource, AclMode requiredPerms)
Definition: parse_clause.c:185
CmdType commandType
Definition: parsenodes.h:110
bool hasTargetSRFs
Definition: parsenodes.h:125
#define makeNode(_type_)
Definition: nodes.h:561
RangeTblEntry * addRangeTableEntryForValues(ParseState *pstate, List *exprs, List *coltypes, List *coltypmods, List *colcollations, Alias *alias, bool lateral, bool inFromCl)
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:369
Expr * expr
Definition: primnodes.h:1375
#define ACL_INSERT
Definition: parsenodes.h:72
List * checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
Definition: parse_target.c:972
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
static OnConflictExpr * transformOnConflictClause(ParseState *pstate, OnConflictClause *onConflictClause)
Definition: analyze.c:1003
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:742
#define UNKNOWNOID
Definition: pg_type.h:431
List * cteList
Definition: parsenodes.h:133
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool hasSubLinks
Definition: parsenodes.h:126
void assign_query_collations(ParseState *pstate, Query *query)
bool p_is_insert
Definition: parse_node.h:186
List * p_ctenamespace
Definition: parse_node.h:181
List * p_joinlist
Definition: parse_node.h:176
bool hasModifyingCTE
Definition: parsenodes.h:129
WithClause * withClause
Definition: parsenodes.h:1561
#define elog
Definition: elog.h:219
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
OnConflictAction action
Definition: parsenodes.h:1374
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
long val
Definition: informix.c:689
List * p_joinexprs
Definition: parse_node.h:175
Node * limitCount
Definition: parsenodes.h:1559
static List * transformInsertRow(ParseState *pstate, List *exprlist, List *stmtcols, List *icolumns, List *attrnos, bool strip_indirection)
Definition: analyze.c:899
List * p_rtable
Definition: parse_node.h:174

◆ transformLockingClause()

static void transformLockingClause ( ParseState pstate,
Query qry,
LockingClause lc,
bool  pushedDown 
)
static

Definition at line 2714 of file analyze.c.

References ACL_SELECT_FOR_UPDATE, Alias::aliasname, applyLockingClause(), RangeVar::catalogname, CheckSelectLocking(), elog, RangeTblEntry::eref, ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, i, LCS_asString(), lfirst, RangeVar::location, LockingClause::lockedRels, makeNode, NIL, parser_errposition(), RangeVar::relname, RangeTblEntry::requiredPerms, Query::rtable, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, RangeVar::schemaname, LockingClause::strength, RangeTblEntry::subquery, and LockingClause::waitPolicy.

Referenced by transformSelectStmt(), and transformSetOperationStmt().

2716 {
2717  List *lockedRels = lc->lockedRels;
2718  ListCell *l;
2719  ListCell *rt;
2720  Index i;
2721  LockingClause *allrels;
2722 
2723  CheckSelectLocking(qry, lc->strength);
2724 
2725  /* make a clause we can pass down to subqueries to select all rels */
2726  allrels = makeNode(LockingClause);
2727  allrels->lockedRels = NIL; /* indicates all rels */
2728  allrels->strength = lc->strength;
2729  allrels->waitPolicy = lc->waitPolicy;
2730 
2731  if (lockedRels == NIL)
2732  {
2733  /* all regular tables used in query */
2734  i = 0;
2735  foreach(rt, qry->rtable)
2736  {
2737  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
2738 
2739  ++i;
2740  switch (rte->rtekind)
2741  {
2742  case RTE_RELATION:
2743  applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
2744  pushedDown);
2746  break;
2747  case RTE_SUBQUERY:
2748  applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
2749  pushedDown);
2750 
2751  /*
2752  * FOR UPDATE/SHARE of subquery is propagated to all of
2753  * subquery's rels, too. We could do this later (based on
2754  * the marking of the subquery RTE) but it is convenient
2755  * to have local knowledge in each query level about which
2756  * rels need to be opened with RowShareLock.
2757  */
2758  transformLockingClause(pstate, rte->subquery,
2759  allrels, true);
2760  break;
2761  default:
2762  /* ignore JOIN, SPECIAL, FUNCTION, VALUES, CTE RTEs */
2763  break;
2764  }
2765  }
2766  }
2767  else
2768  {
2769  /* just the named tables */
2770  foreach(l, lockedRels)
2771  {
2772  RangeVar *thisrel = (RangeVar *) lfirst(l);
2773 
2774  /* For simplicity we insist on unqualified alias names here */
2775  if (thisrel->catalogname || thisrel->schemaname)
2776  ereport(ERROR,
2777  (errcode(ERRCODE_SYNTAX_ERROR),
2778  /*------
2779  translator: %s is a SQL row locking clause such as FOR UPDATE */
2780  errmsg("%s must specify unqualified relation names",
2781  LCS_asString(lc->strength)),
2782  parser_errposition(pstate, thisrel->location)));
2783 
2784  i = 0;
2785  foreach(rt, qry->rtable)
2786  {
2787  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
2788 
2789  ++i;
2790  if (strcmp(rte->eref->aliasname, thisrel->relname) == 0)
2791  {
2792  switch (rte->rtekind)
2793  {
2794  case RTE_RELATION:
2795  applyLockingClause(qry, i, lc->strength,
2796  lc->waitPolicy, pushedDown);
2798  break;
2799  case RTE_SUBQUERY:
2800  applyLockingClause(qry, i, lc->strength,
2801  lc->waitPolicy, pushedDown);
2802  /* see comment above */
2803  transformLockingClause(pstate, rte->subquery,
2804  allrels, true);
2805  break;
2806  case RTE_JOIN:
2807  ereport(ERROR,
2808  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2809  /*------
2810  translator: %s is a SQL row locking clause such as FOR UPDATE */
2811  errmsg("%s cannot be applied to a join",
2812  LCS_asString(lc->strength)),
2813  parser_errposition(pstate, thisrel->location)));
2814  break;
2815  case RTE_FUNCTION:
2816  ereport(ERROR,
2817  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2818  /*------
2819  translator: %s is a SQL row locking clause such as FOR UPDATE */
2820  errmsg("%s cannot be applied to a function",
2821  LCS_asString(lc->strength)),
2822  parser_errposition(pstate, thisrel->location)));
2823  break;
2824  case RTE_TABLEFUNC:
2825  ereport(ERROR,
2826  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2827  /*------
2828  translator: %s is a SQL row locking clause such as FOR UPDATE */
2829  errmsg("%s cannot be applied to a table function",
2830  LCS_asString(lc->strength)),
2831  parser_errposition(pstate, thisrel->location)));
2832  break;
2833  case RTE_VALUES:
2834  ereport(ERROR,
2835  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2836  /*------
2837  translator: %s is a SQL row locking clause such as FOR UPDATE */
2838  errmsg("%s cannot be applied to VALUES",
2839  LCS_asString(lc->strength)),
2840  parser_errposition(pstate, thisrel->location)));
2841  break;
2842  case RTE_CTE:
2843  ereport(ERROR,
2844  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2845  /*------
2846  translator: %s is a SQL row locking clause such as FOR UPDATE */
2847  errmsg("%s cannot be applied to a WITH query",
2848  LCS_asString(lc->strength)),
2849  parser_errposition(pstate, thisrel->location)));
2850  break;
2851  case RTE_NAMEDTUPLESTORE:
2852  ereport(ERROR,
2853  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2854  /*------
2855  translator: %s is a SQL row locking clause such as FOR UPDATE */
2856  errmsg("%s cannot be applied to a named tuplestore",
2857  LCS_asString(lc->strength)),
2858  parser_errposition(pstate, thisrel->location)));
2859  break;
2860  default:
2861  elog(ERROR, "unrecognized RTE type: %d",
2862  (int) rte->rtekind);
2863  break;
2864  }
2865  break; /* out of foreach loop */
2866  }
2867  }
2868  if (rt == NULL)
2869  ereport(ERROR,
2871  /*------
2872  translator: %s is a SQL row locking clause such as FOR UPDATE */
2873  errmsg("relation \"%s\" in %s clause not found in FROM clause",
2874  thisrel->relname,
2875  LCS_asString(lc->strength)),
2876  parser_errposition(pstate, thisrel->location)));
2877  }
2878  }
2879 }
List * lockedRels
Definition: parsenodes.h:745
#define NIL
Definition: pg_list.h:69
static void transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc, bool pushedDown)
Definition: analyze.c:2714
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2625
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:61
int errcode(int sqlerrcode)
Definition: elog.c:575
AclMode requiredPerms
Definition: parsenodes.h:1067
char * schemaname
Definition: primnodes.h:67
int location
Definition: primnodes.h:73
char * relname
Definition: primnodes.h:68
void CheckSelectLocking(Query *qry, LockClauseStrength strength)
Definition: analyze.c:2650
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
LockClauseStrength strength
Definition: parsenodes.h:746
#define ereport(elevel, rest)
Definition: elog.h:122
unsigned int Index
Definition: c.h:431
#define makeNode(_type_)
Definition: nodes.h:561
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
#define ACL_SELECT_FOR_UPDATE
Definition: parsenodes.h:88
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
RTEKind rtekind
Definition: parsenodes.h:959
Query * subquery
Definition: parsenodes.h:982
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define elog
Definition: elog.h:219
Alias * eref
Definition: parsenodes.h:1063
Definition: pg_list.h:45
LockWaitPolicy waitPolicy
Definition: parsenodes.h:747
char * catalogname
Definition: primnodes.h:66
void applyLockingClause(Query *qry, Index rtindex, LockClauseStrength strength, LockWaitPolicy waitPolicy, bool pushedDown)
Definition: analyze.c:2885

◆ transformOnConflictClause()

static OnConflictExpr * transformOnConflictClause ( ParseState pstate,
OnConflictClause onConflictClause 
)
static

Definition at line 1003 of file analyze.c.

References OnConflictClause::action, OnConflictExpr::action, addRangeTableEntryForRelation(), addRTEtoQuery(), OnConflictExpr::arbiterElems, OnConflictExpr::arbiterWhere, OnConflictExpr::constraint, ereport, errcode(), errmsg(), ERROR, OnConflictExpr::exclRelIndex, OnConflictExpr::exclRelTlist, EXPR_KIND_WHERE, INT4OID, InvalidAttrNumber, InvalidOid, lappend(), list_length(), makeAlias(), makeNode, makeNullConst(), makeTargetEntry(), makeVar(), name, NameStr, NIL, ONCONFLICT_UPDATE, OnConflictExpr::onConflictSet, OnConflictExpr::onConflictWhere, ParseState::p_is_insert, ParseState::p_rtable, ParseState::p_target_rangetblentry, ParseState::p_target_relation, pstrdup(), RelationData::rd_att, RelationData::rd_partdesc, RelationData::rd_rel, RelationGetRelationName, RangeTblEntry::relkind, RELKIND_COMPOSITE_TYPE, OnConflictClause::targetList, transformOnConflictArbiter(), transformUpdateTargetList(), transformWhereClause(), TupleDescAttr, and OnConflictClause::whereClause.

Referenced by transformInsertStmt().

1005 {
1006  List *arbiterElems;
1007  Node *arbiterWhere;
1008  Oid arbiterConstraint;
1009  List *onConflictSet = NIL;
1010  Node *onConflictWhere = NULL;
1011  RangeTblEntry *exclRte = NULL;
1012  int exclRelIndex = 0;
1013  List *exclRelTlist = NIL;
1014  OnConflictExpr *result;
1015 
1016  /* Process the arbiter clause, ON CONFLICT ON (...) */
1017  transformOnConflictArbiter(pstate, onConflictClause, &arbiterElems,
1018  &arbiterWhere, &arbiterConstraint);
1019 
1020  /* Process DO UPDATE */
1021  if (onConflictClause->action == ONCONFLICT_UPDATE)
1022  {
1023  Relation targetrel = pstate->p_target_relation;
1024  Var *var;
1025  TargetEntry *te;
1026  int attno;
1027 
1028  if (targetrel->rd_partdesc)
1029  ereport(ERROR,
1030  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1031  errmsg("%s cannot be applied to partitioned table \"%s\"",
1032  "ON CONFLICT DO UPDATE",
1033  RelationGetRelationName(targetrel))));
1034 
1035  /*
1036  * All INSERT expressions have been parsed, get ready for potentially
1037  * existing SET statements that need to be processed like an UPDATE.
1038  */
1039  pstate->p_is_insert = false;
1040 
1041  /*
1042  * Add range table entry for the EXCLUDED pseudo relation; relkind is
1043  * set to composite to signal that we're not dealing with an actual
1044  * relation.
1045  */
1046  exclRte = addRangeTableEntryForRelation(pstate,
1047  targetrel,
1048  makeAlias("excluded", NIL),
1049  false, false);
1050  exclRte->relkind = RELKIND_COMPOSITE_TYPE;
1051  exclRelIndex = list_length(pstate->p_rtable);
1052 
1053  /*
1054  * Build a targetlist representing the columns of the EXCLUDED pseudo
1055  * relation. Have to be careful to use resnos that correspond to
1056  * attnos of the underlying relation.
1057  */
1058  for (attno = 0; attno < targetrel->rd_rel->relnatts; attno++)
1059  {
1060  Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno);
1061  char *name;
1062 
1063  if (attr->attisdropped)
1064  {
1065  /*
1066  * can't use atttypid here, but it doesn't really matter what
1067  * type the Const claims to be.
1068  */
1069  var = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
1070  name = "";
1071  }
1072  else
1073  {
1074  var = makeVar(exclRelIndex, attno + 1,
1075  attr->atttypid, attr->atttypmod,
1076  attr->attcollation,
1077  0);
1078  name = pstrdup(NameStr(attr->attname));
1079  }
1080 
1081  te = makeTargetEntry((Expr *) var,
1082  attno + 1,
1083  name,
1084  false);
1085 
1086  /* don't require select access yet */
1087  exclRelTlist = lappend(exclRelTlist, te);
1088  }
1089 
1090  /*
1091  * Add a whole-row-Var entry to support references to "EXCLUDED.*".
1092  * Like the other entries in exclRelTlist, its resno must match the
1093  * Var's varattno, else the wrong things happen while resolving
1094  * references in setrefs.c. This is against normal conventions for
1095  * targetlists, but it's okay since we don't use this as a real tlist.
1096  */
1097  var = makeVar(exclRelIndex, InvalidAttrNumber,
1098  targetrel->rd_rel->reltype,
1099  -1, InvalidOid, 0);
1100  te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
1101  exclRelTlist = lappend(exclRelTlist, te);
1102 
1103  /*
1104  * Add EXCLUDED and the target RTE to the namespace, so that they can
1105  * be used in the UPDATE statement.
1106  */
1107  addRTEtoQuery(pstate, exclRte, false, true, true);
1108  addRTEtoQuery(pstate, pstate->p_target_rangetblentry,
1109  false, true, true);
1110 
1111  onConflictSet =
1112  transformUpdateTargetList(pstate, onConflictClause->targetList);
1113 
1114  onConflictWhere = transformWhereClause(pstate,
1115  onConflictClause->whereClause,
1116  EXPR_KIND_WHERE, "WHERE");
1117  }
1118 
1119  /* Finally, build ON CONFLICT DO [NOTHING | UPDATE] expression */
1120  result = makeNode(OnConflictExpr);
1121 
1122  result->action = onConflictClause->action;
1123  result->arbiterElems = arbiterElems;
1124  result->arbiterWhere = arbiterWhere;
1125  result->constraint = arbiterConstraint;
1126  result->onConflictSet = onConflictSet;
1127  result->onConflictWhere = onConflictWhere;
1128  result->exclRelIndex = exclRelIndex;
1129  result->exclRelTlist = exclRelTlist;
1130 
1131  return result;
1132 }
#define NIL
Definition: pg_list.h:69
struct PartitionDescData * rd_partdesc
Definition: rel.h:131
static List * transformUpdateTargetList(ParseState *pstate, List *targetList)
Definition: analyze.c:2272
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
char * pstrdup(const char *in)
Definition: mcxt.c:1063
#define INT4OID
Definition: pg_type.h:316
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
void transformOnConflictArbiter(ParseState *pstate, OnConflictClause *onConflictClause, List **arbiterExpr, Node **arbiterWhere, Oid *constraint)
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:163
#define RELKIND_COMPOSITE_TYPE
Definition: pg_class.h:166
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:336
List * arbiterElems
Definition: primnodes.h:1497
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:386
#define ERROR
Definition: elog.h:43
List * exclRelTlist
Definition: primnodes.h:1506
#define RelationGetRelationName(relation)
Definition: rel.h:445
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define ereport(elevel, rest)
Definition: elog.h:122
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:237
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:67
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
List * lappend(List *list, void *datum)
Definition: list.c:128
OnConflictAction action
Definition: primnodes.h:1494
RangeTblEntry * p_target_rangetblentry
Definition: parse_node.h:185
TupleDesc rd_att
Definition: rel.h:115
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:561
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
static int list_length(const List *l)
Definition: pg_list.h:89
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, Alias *alias, bool inh, bool inFromCl)
const char * name
Definition: encode.c:521
#define InvalidAttrNumber
Definition: attnum.h:23
Node * arbiterWhere
Definition: primnodes.h:1499
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation p_target_relation
Definition: parse_node.h:184
bool p_is_insert
Definition: parse_node.h:186
List * onConflictSet
Definition: primnodes.h:1503
#define NameStr(name)
Definition: c.h:565
Node * onConflictWhere
Definition: primnodes.h:1504
OnConflictAction action
Definition: parsenodes.h:1374
Definition: pg_list.h:45
List * p_rtable
Definition: parse_node.h:174

◆ transformOptionalSelectInto()

static Query * transformOptionalSelectInto ( ParseState pstate,
Node parseTree 
)
static

Definition at line 215 of file analyze.c.

References Assert, CreateTableAsStmt::into, SelectStmt::intoClause, CreateTableAsStmt::is_select_into, IsA, SelectStmt::larg, makeNode, OBJECT_TABLE, SelectStmt::op, CreateTableAsStmt::query, CreateTableAsStmt::relkind, SETOP_NONE, and transformStmt().

Referenced by transformExplainStmt(), and transformTopLevelStmt().

216 {
217  if (IsA(parseTree, SelectStmt))
218  {
219  SelectStmt *stmt = (SelectStmt *) parseTree;
220 
221  /* If it's a set-operation tree, drill down to leftmost SelectStmt */
222  while (stmt && stmt->op != SETOP_NONE)
223  stmt = stmt->larg;
224  Assert(stmt && IsA(stmt, SelectStmt) &&stmt->larg == NULL);
225 
226  if (stmt->intoClause)
227  {
229 
230  ctas->query = parseTree;
231  ctas->into = stmt->intoClause;
232  ctas->relkind = OBJECT_TABLE;
233  ctas->is_select_into = true;
234 
235  /*
236  * Remove the intoClause from the SelectStmt. This makes it safe
237  * for transformSelectStmt to complain if it finds intoClause set
238  * (implying that the INTO appeared in a disallowed place).
239  */
240  stmt->intoClause = NULL;
241 
242  parseTree = (Node *) ctas;
243  }
244  }
245 
246  return transformStmt(pstate, parseTree);
247 }
struct SelectStmt * larg
Definition: parsenodes.h:1568
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
IntoClause * intoClause
Definition: parsenodes.h:1535
Definition: nodes.h:513
ObjectType relkind
Definition: parsenodes.h:3188
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:254
SetOperation op
Definition: parsenodes.h:1566
IntoClause * into
Definition: parsenodes.h:3187
#define makeNode(_type_)
Definition: nodes.h:561
#define Assert(condition)
Definition: c.h:688

◆ transformReturningList()

static List * transformReturningList ( ParseState pstate,
List returningList 
)
static

Definition at line 2344 of file analyze.c.

References ereport, errcode(), errmsg(), ERROR, EXPR_KIND_RETURNING, exprLocation(), linitial, markTargetListOrigins(), NIL, ParseState::p_next_resno, ParseState::p_resolve_unknowns, parser_errposition(), resolveTargetListUnknowns(), and transformTargetList().

Referenced by transformDeleteStmt(), transformInsertStmt(), and transformUpdateStmt().

2345 {
2346  List *rlist;
2347  int save_next_resno;
2348 
2349  if (returningList == NIL)
2350  return NIL; /* nothing to do */
2351 
2352  /*
2353  * We need to assign resnos starting at one in the RETURNING list. Save
2354  * and restore the main tlist's value of p_next_resno, just in case
2355  * someone looks at it later (probably won't happen).
2356  */
2357  save_next_resno = pstate->p_next_resno;
2358  pstate->p_next_resno = 1;
2359 
2360  /* transform RETURNING identically to a SELECT targetlist */
2361  rlist = transformTargetList(pstate, returningList, EXPR_KIND_RETURNING);
2362 
2363  /*
2364  * Complain if the nonempty tlist expanded to nothing (which is possible
2365  * if it contains only a star-expansion of a zero-column table). If we
2366  * allow this, the parsed Query will look like it didn't have RETURNING,
2367  * with results that would probably surprise the user.
2368  */
2369  if (rlist == NIL)
2370  ereport(ERROR,
2371  (errcode(ERRCODE_SYNTAX_ERROR),
2372  errmsg("RETURNING must have at least one column"),
2373  parser_errposition(pstate,
2374  exprLocation(linitial(returningList)))));
2375 
2376  /* mark column origins */
2377  markTargetListOrigins(pstate, rlist);
2378 
2379  /* resolve any still-unresolved output columns as being type text */
2380  if (pstate->p_resolve_unknowns)
2381  resolveTargetListUnknowns(pstate, rlist);
2382 
2383  /* restore state */
2384  pstate->p_next_resno = save_next_resno;
2385 
2386  return rlist;
2387 }
#define NIL
Definition: pg_list.h:69
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1186
int errcode(int sqlerrcode)
Definition: elog.c:575
List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind)
Definition: parse_target.c:131
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
bool p_resolve_unknowns
Definition: parse_node.h:194
int p_next_resno
Definition: parse_node.h:189
#define ereport(elevel, rest)
Definition: elog.h:122
void resolveTargetListUnknowns(ParseState *pstate, List *targetlist)
Definition: parse_target.c:299
void markTargetListOrigins(ParseState *pstate, List *targetlist)
Definition: parse_target.c:329
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int errmsg(const char *fmt,...)
Definition: elog.c:797
Definition: pg_list.h:45

◆ transformSelectStmt()

static Query * transformSelectStmt ( ParseState pstate,
SelectStmt stmt 
)
static

Definition at line 1187 of file analyze.c.

References assign_query_collations(), CMD_SELECT, Query::commandType, Query::cteList, Query::distinctClause, SelectStmt::distinctClause, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_GROUP_BY, EXPR_KIND_HAVING, EXPR_KIND_LIMIT, EXPR_KIND_OFFSET, EXPR_KIND_ORDER_BY, EXPR_KIND_SELECT_TARGET, EXPR_KIND_WHERE, exprLocation(), SelectStmt::fromClause, Query::groupClause, SelectStmt::groupClause, Query::groupingSets, Query::hasAggs, Query::hasDistinctOn, Query::hasModifyingCTE, Query::hasRecursive, Query::hasSubLinks, Query::hasTargetSRFs, Query::hasWindowFuncs, SelectStmt::havingClause, Query::havingQual, SelectStmt::intoClause, Query::jointree, lfirst, Query::limitCount, SelectStmt::limitCount, Query::limitOffset, SelectStmt::limitOffset, linitial, SelectStmt::lockingClause, makeFromExpr(), makeNode, markTargetListOrigins(), NIL, ParseState::p_hasAggs, ParseState::p_hasModifyingCTE, ParseState::p_hasSubLinks, ParseState::p_hasTargetSRFs, ParseState::p_hasWindowFuncs, ParseState::p_joinlist, ParseState::p_locking_clause, ParseState::p_resolve_unknowns, ParseState::p_rtable, ParseState::p_windowdefs, parseCheckAggregates(), parser_errposition(), WithClause::recursive, resolveTargetListUnknowns(), Query::rtable, Query::sortClause, SelectStmt::sortClause, Query::targetList, SelectStmt::targetList, transformDistinctClause(), transformDistinctOnClause(), transformFromClause(), transformGroupClause(), transformLimitClause(), transformLockingClause(), transformSortClause(), transformTargetList(), transformWhereClause(), transformWindowDefinitions(), transformWithClause(), SelectStmt::whereClause, Query::windowClause, SelectStmt::windowClause, and SelectStmt::withClause.

Referenced by transformStmt().

1188 {
1189  Query *qry = makeNode(Query);
1190  Node *qual;
1191  ListCell *l;
1192 
1193  qry->commandType = CMD_SELECT;
1194 
1195  /* process the WITH clause independently of all else */
1196  if (stmt->withClause)
1197  {
1198  qry->hasRecursive = stmt->withClause->recursive;
1199  qry->cteList = transformWithClause(pstate, stmt->withClause);
1200  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1201  }
1202 
1203  /* Complain if we get called from someplace where INTO is not allowed */
1204  if (stmt->intoClause)
1205  ereport(ERROR,
1206  (errcode(ERRCODE_SYNTAX_ERROR),
1207  errmsg("SELECT ... INTO is not allowed here"),
1208  parser_errposition(pstate,
1209  exprLocation((Node *) stmt->intoClause))));
1210 
1211  /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
1212  pstate->p_locking_clause = stmt->lockingClause;
1213 
1214  /* make WINDOW info available for window functions, too */
1215  pstate->p_windowdefs = stmt->windowClause;
1216 
1217  /* process the FROM clause */
1218  transformFromClause(pstate, stmt->fromClause);
1219 
1220  /* transform targetlist */
1221  qry->targetList = transformTargetList(pstate, stmt->targetList,
1223 
1224  /* mark column origins */
1225  markTargetListOrigins(pstate, qry->targetList);
1226 
1227  /* transform WHERE */
1228  qual = transformWhereClause(pstate, stmt->whereClause,
1229  EXPR_KIND_WHERE, "WHERE");
1230 
1231  /* initial processing of HAVING clause is much like WHERE clause */
1232  qry->havingQual = transformWhereClause(pstate, stmt->havingClause,
1233  EXPR_KIND_HAVING, "HAVING");
1234 
1235  /*
1236  * Transform sorting/grouping stuff. Do ORDER BY first because both
1237  * transformGroupClause and transformDistinctClause need the results. Note
1238  * that these functions can also change the targetList, so it's passed to
1239  * them by reference.
1240  */
1241  qry->sortClause = transformSortClause(pstate,
1242  stmt->sortClause,
1243  &qry->targetList,
1245  false /* allow SQL92 rules */ );
1246 
1247  qry->groupClause = transformGroupClause(pstate,
1248  stmt->groupClause,
1249  &qry->groupingSets,
1250  &qry->targetList,
1251  qry->sortClause,
1253  false /* allow SQL92 rules */ );
1254 
1255  if (stmt->distinctClause == NIL)
1256  {
1257  qry->distinctClause = NIL;
1258  qry->hasDistinctOn = false;
1259  }
1260  else if (linitial(stmt->distinctClause) == NULL)
1261  {
1262  /* We had SELECT DISTINCT */
1264  &qry->targetList,
1265  qry->sortClause,
1266  false);
1267  qry->hasDistinctOn = false;
1268  }
1269  else
1270  {
1271  /* We had SELECT DISTINCT ON */
1273  stmt->distinctClause,
1274  &qry->targetList,
1275  qry->sortClause);
1276  qry->hasDistinctOn = true;
1277  }
1278 
1279  /* transform LIMIT */
1280  qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
1281  EXPR_KIND_OFFSET, "OFFSET");
1282  qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
1283  EXPR_KIND_LIMIT, "LIMIT");
1284 
1285  /* transform window clauses after we have seen all window functions */
1287  pstate->p_windowdefs,
1288  &qry->targetList);
1289 
1290  /* resolve any still-unresolved output columns as being type text */
1291  if (pstate->p_resolve_unknowns)
1292  resolveTargetListUnknowns(pstate, qry->targetList);
1293 
1294  qry->rtable = pstate->p_rtable;
1295  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
1296 
1297  qry->hasSubLinks = pstate->p_hasSubLinks;
1298  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
1299  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
1300  qry->hasAggs = pstate->p_hasAggs;
1301  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
1302  parseCheckAggregates(pstate, qry);
1303 
1304  foreach(l, stmt->lockingClause)
1305  {
1306  transformLockingClause(pstate, qry,
1307  (LockingClause *) lfirst(l), false);
1308  }
1309 
1310  assign_query_collations(pstate, qry);
1311 
1312  return qry;
1313 }
Node * limitOffset
Definition: parsenodes.h:158
#define NIL
Definition: pg_list.h:69
static void transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc, bool pushedDown)
Definition: analyze.c:2714
bool p_hasSubLinks
Definition: parse_node.h:203
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:284
List * sortClause
Definition: parsenodes.h:156
List * transformDistinctOnClause(ParseState *pstate, List *distinctlist, List **targetlist, List *sortClause)
IntoClause * intoClause
Definition: parsenodes.h:1535
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1186
List * fromClause
Definition: parsenodes.h:1537
FromExpr * jointree
Definition: parsenodes.h:136
List * transformSortClause(ParseState *pstate, List *orderlist, List **targetlist, ParseExprKind exprKind, bool useSQL99)
Node * limitOffset
Definition: parsenodes.h:1558
bool hasAggs
Definition: parsenodes.h:123
bool p_hasTargetSRFs
Definition: parse_node.h:202
List * groupingSets
Definition: parsenodes.h:148
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
bool p_hasAggs
Definition: parse_node.h:200
Node * transformLimitClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
void parseCheckAggregates(ParseState *pstate, Query *qry)
Definition: parse_agg.c:1011
bool hasDistinctOn
Definition: parsenodes.h:127
List * windowClause
Definition: parsenodes.h:152
List * targetList
Definition: parsenodes.h:138
bool p_hasWindowFuncs
Definition: parse_node.h:201
bool hasRecursive
Definition: parsenodes.h:128
List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind)
Definition: parse_target.c:131
List * distinctClause
Definition: parsenodes.h:1533
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
List * distinctClause
Definition: parsenodes.h:154
#define ERROR
Definition: elog.h:43
List * p_windowdefs
Definition: parse_node.h:187
bool p_resolve_unknowns
Definition: parse_node.h:194
Node * limitCount
Definition: parsenodes.h:159
List * sortClause
Definition: parsenodes.h:1557
List * targetList
Definition: parsenodes.h:1536
List * transformGroupClause(ParseState *pstate, List *grouplist, List **groupingSets, List **targetlist, List *sortClause, ParseExprKind exprKind, bool useSQL99)
List * p_locking_clause
Definition: parse_node.h:191
bool recursive
Definition: parsenodes.h:1346
#define ereport(elevel, rest)
Definition: elog.h:122
List * lockingClause
Definition: parsenodes.h:1560
bool p_hasModifyingCTE
Definition: parse_node.h:204
List * transformWindowDefinitions(ParseState *pstate, List *windowdefs, List **targetlist)
void resolveTargetListUnknowns(ParseState *pstate, List *targetlist)
Definition: parse_target.c:299
void transformFromClause(ParseState *pstate, List *frmList)
Definition: parse_clause.c:119
List * windowClause
Definition: parsenodes.h:1541
CmdType commandType
Definition: parsenodes.h:110
bool hasTargetSRFs
Definition: parsenodes.h:125
#define makeNode(_type_)
Definition: nodes.h:561
#define lfirst(lc)
Definition: pg_list.h:106
bool hasWindowFuncs
Definition: parsenodes.h:124
void markTargetListOrigins(ParseState *pstate, List *targetlist)
Definition: parse_target.c:329
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
List * groupClause
Definition: parsenodes.h:1539
List * cteList
Definition: parsenodes.h:133
List * groupClause
Definition: parsenodes.h:146
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool hasSubLinks
Definition: parsenodes.h:126
void assign_query_collations(ParseState *pstate, Query *query)
Node * havingClause
Definition: parsenodes.h:1540
List * p_joinlist
Definition: parse_node.h:176
bool hasModifyingCTE
Definition: parsenodes.h:129
WithClause * withClause
Definition: parsenodes.h:1561
List * transformDistinctClause(ParseState *pstate, List **targetlist, List *sortClause, bool is_agg)
Node * havingQual
Definition: parsenodes.h:150
Node * limitCount
Definition: parsenodes.h:1559
Node * whereClause
Definition: parsenodes.h:1538
List * p_rtable
Definition: parse_node.h:174

◆ transformSetOperationStmt()

static Query * transformSetOperationStmt ( ParseState pstate,
SelectStmt stmt 
)
static

Definition at line 1561 of file analyze.c.

References addRangeTableEntryForJoin(), addRTEtoQuery(), Assert, assign_query_collations(), castNode, CMD_SELECT, SetOperationStmt::colCollations, SetOperationStmt::colTypes, SetOperationStmt::colTypmods, Query::commandType, Query::cteList, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, TargetEntry::expr, EXPR_KIND_LIMIT, EXPR_KIND_OFFSET, EXPR_KIND_ORDER_BY, exprLocation(), forthree, Query::groupClause, Query::groupingSets, Query::hasAggs, Query::hasModifyingCTE, Query::hasRecursive, Query::hasSubLinks, Query::hasTargetSRFs, Query::hasWindowFuncs, Query::havingQual, SelectStmt::intoClause, IsA, JOIN_INNER, Query::jointree, lappend(), SelectStmt::larg, SetOperationStmt::larg, LCS_asString(), lfirst, lfirst_int, lfirst_oid, Query::limitCount, SelectStmt::limitCount, Query::limitOffset, SelectStmt::limitOffset, linitial, list_head(), list_length(), list_nth(), list_truncate(), lnext, Var::location, SelectStmt::lockingClause, makeFromExpr(), makeNode, makeString(), makeTargetEntry(), makeVar(), NIL, SelectStmt::op, ParseState::p_hasAggs, ParseState::p_hasModifyingCTE, ParseState::p_hasSubLinks, ParseState::p_hasTargetSRFs, ParseState::p_hasWindowFuncs, ParseState::p_joinlist, ParseState::p_namespace, ParseState::p_next_resno, ParseState::p_rtable, parseCheckAggregates(), parser_errposition(), pstrdup(), WithClause::recursive, TargetEntry::resjunk, TargetEntry::resname, TargetEntry::resno, rt_fetch, Query::rtable, SETOP_NONE, Query::setOperations, Query::sortClause, SelectStmt::sortClause, Query::targetList, transformLimitClause(), transformLockingClause(), transformSetOperationTree(), transformSortClause(), transformWithClause(), and SelectStmt::withClause.

Referenced by transformStmt().

1562 {
1563  Query *qry = makeNode(Query);
1564  SelectStmt *leftmostSelect;
1565  int leftmostRTI;
1566  Query *leftmostQuery;
1567  SetOperationStmt *sostmt;
1568  List *sortClause;
1569  Node *limitOffset;
1570  Node *limitCount;
1571  List *lockingClause;
1572  WithClause *withClause;
1573  Node *node;
1574  ListCell *left_tlist,
1575  *lct,
1576  *lcm,
1577  *lcc,
1578  *l;
1579  List *targetvars,
1580  *targetnames,
1581  *sv_namespace;
1582  int sv_rtable_length;
1583  RangeTblEntry *jrte;
1584  int tllen;
1585 
1586  qry->commandType = CMD_SELECT;
1587 
1588  /*
1589  * Find leftmost leaf SelectStmt. We currently only need to do this in
1590  * order to deliver a suitable error message if there's an INTO clause
1591  * there, implying the set-op tree is in a context that doesn't allow
1592  * INTO. (transformSetOperationTree would throw error anyway, but it
1593  * seems worth the trouble to throw a different error for non-leftmost
1594  * INTO, so we produce that error in transformSetOperationTree.)
1595  */
1596  leftmostSelect = stmt->larg;
1597  while (leftmostSelect && leftmostSelect->op != SETOP_NONE)
1598  leftmostSelect = leftmostSelect->larg;
1599  Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
1600  leftmostSelect->larg == NULL);
1601  if (leftmostSelect->intoClause)
1602  ereport(ERROR,
1603  (errcode(ERRCODE_SYNTAX_ERROR),
1604  errmsg("SELECT ... INTO is not allowed here"),
1605  parser_errposition(pstate,
1606  exprLocation((Node *) leftmostSelect->intoClause))));
1607 
1608  /*
1609  * We need to extract ORDER BY and other top-level clauses here and not
1610  * let transformSetOperationTree() see them --- else it'll just recurse
1611  * right back here!
1612  */
1613  sortClause = stmt->sortClause;
1614  limitOffset = stmt->limitOffset;
1615  limitCount = stmt->limitCount;
1616  lockingClause = stmt->lockingClause;
1617  withClause = stmt->withClause;
1618 
1619  stmt->sortClause = NIL;
1620  stmt->limitOffset = NULL;
1621  stmt->limitCount = NULL;
1622  stmt->lockingClause = NIL;
1623  stmt->withClause = NULL;
1624 
1625  /* We don't support FOR UPDATE/SHARE with set ops at the moment. */
1626  if (lockingClause)
1627  ereport(ERROR,
1628  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1629  /*------
1630  translator: %s is a SQL row locking clause such as FOR UPDATE */
1631  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
1633  linitial(lockingClause))->strength))));
1634 
1635  /* Process the WITH clause independently of all else */
1636  if (withClause)
1637  {
1638  qry->hasRecursive = withClause->recursive;
1639  qry->cteList = transformWithClause(pstate, withClause);
1640  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1641  }
1642 
1643  /*
1644  * Recursively transform the components of the tree.
1645  */
1646  sostmt = castNode(SetOperationStmt,
1647  transformSetOperationTree(pstate, stmt, true, NULL));
1648  Assert(sostmt);
1649  qry->setOperations = (Node *) sostmt;
1650 
1651  /*
1652  * Re-find leftmost SELECT (now it's a sub-query in rangetable)
1653  */
1654  node = sostmt->larg;
1655  while (node && IsA(node, SetOperationStmt))
1656  node = ((SetOperationStmt *) node)->larg;
1657  Assert(node && IsA(node, RangeTblRef));
1658  leftmostRTI = ((RangeTblRef *) node)->rtindex;
1659  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
1660  Assert(leftmostQuery != NULL);
1661 
1662  /*
1663  * Generate dummy targetlist for outer query using column names of
1664  * leftmost select and common datatypes/collations of topmost set
1665  * operation. Also make lists of the dummy vars and their names for use
1666  * in parsing ORDER BY.
1667  *
1668  * Note: we use leftmostRTI as the varno of the dummy variables. It
1669  * shouldn't matter too much which RT index they have, as long as they
1670  * have one that corresponds to a real RT entry; else funny things may
1671  * happen when the tree is mashed by rule rewriting.
1672  */
1673  qry->targetList = NIL;
1674  targetvars = NIL;
1675  targetnames = NIL;
1676  left_tlist = list_head(leftmostQuery->targetList);
1677 
1678  forthree(lct, sostmt->colTypes,
1679  lcm, sostmt->colTypmods,
1680  lcc, sostmt->colCollations)
1681  {
1682  Oid colType = lfirst_oid(lct);
1683  int32 colTypmod = lfirst_int(lcm);
1684  Oid colCollation = lfirst_oid(lcc);
1685  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
1686  char *colName;
1687  TargetEntry *tle;
1688  Var *var;
1689 
1690  Assert(!lefttle->resjunk);
1691  colName = pstrdup(lefttle->resname);
1692  var = makeVar(leftmostRTI,
1693  lefttle->resno,
1694  colType,
1695  colTypmod,
1696  colCollation,
1697  0);
1698  var->location = exprLocation((Node *) lefttle->expr);
1699  tle = makeTargetEntry((Expr *) var,
1700  (AttrNumber) pstate->p_next_resno++,
1701  colName,
1702  false);
1703  qry->targetList = lappend(qry->targetList, tle);
1704  targetvars = lappend(targetvars, var);
1705  targetnames = lappend(targetnames, makeString(colName));
1706  left_tlist = lnext(left_tlist);
1707  }
1708 
1709  /*
1710  * As a first step towards supporting sort clauses that are expressions
1711  * using the output columns, generate a namespace entry that makes the
1712  * output columns visible. A Join RTE node is handy for this, since we
1713  * can easily control the Vars generated upon matches.
1714  *
1715  * Note: we don't yet do anything useful with such cases, but at least
1716  * "ORDER BY upper(foo)" will draw the right error message rather than
1717  * "foo not found".
1718  */
1719  sv_rtable_length = list_length(pstate->p_rtable);
1720 
1721  jrte = addRangeTableEntryForJoin(pstate,
1722  targetnames,
1723  JOIN_INNER,
1724  targetvars,
1725  NULL,
1726  false);
1727 
1728  sv_namespace = pstate->p_namespace;
1729  pstate->p_namespace = NIL;
1730 
1731  /* add jrte to column namespace only */
1732  addRTEtoQuery(pstate, jrte, false, false, true);
1733 
1734  /*
1735  * For now, we don't support resjunk sort clauses on the output of a
1736  * setOperation tree --- you can only use the SQL92-spec options of
1737  * selecting an output column by name or number. Enforce by checking that
1738  * transformSortClause doesn't add any items to tlist.
1739  */
1740  tllen = list_length(qry->targetList);
1741 
1742  qry->sortClause = transformSortClause(pstate,
1743  sortClause,
1744  &qry->targetList,
1746  false /* allow SQL92 rules */ );
1747 
1748  /* restore namespace, remove jrte from rtable */
1749  pstate->p_namespace = sv_namespace;
1750  pstate->p_rtable = list_truncate(pstate->p_rtable, sv_rtable_length);
1751 
1752  if (tllen != list_length(qry->targetList))
1753  ereport(ERROR,
1754  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1755  errmsg("invalid UNION/INTERSECT/EXCEPT ORDER BY clause"),
1756  errdetail("Only result column names can be used, not expressions or functions."),
1757  errhint("Add the expression/function to every SELECT, or move the UNION into a FROM clause."),
1758  parser_errposition(pstate,
1759  exprLocation(list_nth(qry->targetList, tllen)))));
1760 
1761  qry->limitOffset = transformLimitClause(pstate, limitOffset,
1762  EXPR_KIND_OFFSET, "OFFSET");
1763  qry->limitCount = transformLimitClause(pstate, limitCount,
1764  EXPR_KIND_LIMIT, "LIMIT");
1765 
1766  qry->rtable = pstate->p_rtable;
1767  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
1768 
1769  qry->hasSubLinks = pstate->p_hasSubLinks;
1770  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
1771  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
1772  qry->hasAggs = pstate->p_hasAggs;
1773  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
1774  parseCheckAggregates(pstate, qry);
1775 
1776  foreach(l, lockingClause)
1777  {
1778  transformLockingClause(pstate, qry,
1779  (LockingClause *) lfirst(l), false);
1780  }
1781 
1782  assign_query_collations(pstate, qry);
1783 
1784  return qry;
1785 }
Value * makeString(char *str)
Definition: value.c:53
Node * limitOffset
Definition: parsenodes.h:158
#define NIL
Definition: pg_list.h:69
struct SelectStmt * larg
Definition: parsenodes.h:1568
static void transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc, bool pushedDown)
Definition: analyze.c:2714
bool p_hasSubLinks
Definition: parse_node.h:203
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:284
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2625
int errhint(const char *fmt,...)
Definition: elog.c:987
List * sortClause
Definition: parsenodes.h:156
IntoClause * intoClause
Definition: parsenodes.h:1535
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1186
RangeTblEntry * addRangeTableEntryForJoin(ParseState *pstate, List *colnames, JoinType jointype, List *aliasvars, Alias *alias, bool inFromCl)
FromExpr * jointree
Definition: parsenodes.h:136
#define castNode(_type_, nodeptr)
Definition: nodes.h:582
List * transformSortClause(ParseState *pstate, List *orderlist, List **targetlist, ParseExprKind exprKind, bool useSQL99)
Node * limitOffset
Definition: parsenodes.h:1558
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:203
char * pstrdup(const char *in)
Definition: mcxt.c:1063
bool hasAggs
Definition: parsenodes.h:123
List * list_truncate(List *list, int new_size)
Definition: list.c:350
bool p_hasTargetSRFs
Definition: parse_node.h:202
List * groupingSets
Definition: parsenodes.h:148
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
bool p_hasAggs
Definition: parse_node.h:200
unsigned int Oid
Definition: postgres_ext.h:31
char * resname
Definition: primnodes.h:1377
Definition: primnodes.h:163
Node * transformLimitClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
void parseCheckAggregates(ParseState *pstate, Query *qry)
Definition: parse_agg.c:1011
signed int int32
Definition: c.h:302
List * targetList
Definition: parsenodes.h:138
bool p_hasWindowFuncs
Definition: parse_node.h:201
bool hasRecursive
Definition: parsenodes.h:128
bool resjunk
Definition: primnodes.h:1382
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:107
int location
Definition: primnodes.h:178
Node * limitCount
Definition: parsenodes.h:159
List * p_namespace
Definition: parse_node.h:178
void * list_nth(const List *list, int n)
Definition: list.c:410
List * sortClause
Definition: parsenodes.h:1557
int errdetail(const char *fmt,...)
Definition: elog.c:873
AttrNumber resno
Definition: primnodes.h:1376
int p_next_resno
Definition: parse_node.h:189
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
bool recursive
Definition: parsenodes.h:1346
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
static Node * transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, bool isTopLevel, List **targetlist)
Definition: analyze.c:1802
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:237
List * lockingClause
Definition: parsenodes.h:1560
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:67
bool p_hasModifyingCTE
Definition: parse_node.h:204
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
List * lappend(List *list, void *datum)
Definition: list.c:128
List * colCollations
Definition: parsenodes.h:1605
SetOperation op
Definition: parsenodes.h:1566
CmdType commandType
Definition: parsenodes.h:110
bool hasTargetSRFs
Definition: parsenodes.h:125
#define makeNode(_type_)
Definition: nodes.h:561
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
bool hasWindowFuncs
Definition: parsenodes.h:124
Expr * expr
Definition: primnodes.h:1375
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
List * cteList
Definition: parsenodes.h:133
Node * setOperations
Definition: parsenodes.h:163
List * groupClause
Definition: parsenodes.h:146
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool hasSubLinks
Definition: parsenodes.h:126
void assign_query_collations(ParseState *pstate, Query *query)
List * p_joinlist
Definition: parse_node.h:176
bool hasModifyingCTE
Definition: parsenodes.h:129
WithClause * withClause
Definition: parsenodes.h:1561
Node * havingQual
Definition: parsenodes.h:150
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
Node * limitCount
Definition: parsenodes.h:1559
#define lfirst_oid(lc)
Definition: pg_list.h:108
List * p_rtable
Definition: parse_node.h:174

◆ transformSetOperationTree()

static Node * transformSetOperationTree ( ParseState pstate,
SelectStmt stmt,
bool  isTopLevel,
List **  targetlist 
)
static

Definition at line 1802 of file analyze.c.

References addRangeTableEntryForSubquery(), SelectStmt::all, SetOperationStmt::all, Assert, cancel_parser_errposition_callback(), check_stack_depth(), coerce_to_common_type(), SetOperationStmt::colCollations, SetToDefault::collation, SetOperationStmt::colTypes, SetOperationStmt::colTypmods, contain_vars_of_level(), CommonTableExpr::cterecursive, determineRecursiveColTypes(), SortGroupClause::eqop, ereport, errcode(), errmsg(), ERROR, TargetEntry::expr, exprLocation(), exprType(), exprTypmod(), forboth, get_sort_group_operators(), SetOperationStmt::groupClauses, SortGroupClause::hashable, SelectStmt::intoClause, IsA, lappend(), lappend_int(), lappend_oid(), SelectStmt::larg, SetOperationStmt::larg, LCS_asString(), lfirst, SelectStmt::limitCount, SelectStmt::limitOffset, linitial, list_length(), list_make2, locate_var_of_level(), SetToDefault::location, SelectStmt::lockingClause, makeAlias(), makeNode, makeTargetEntry(), NIL, SortGroupClause::nulls_first, SelectStmt::op, SetOperationStmt::op, ParseState::p_namespace, ParseState::p_parent_cte, ParseState::p_rtable, parse_sub_analyze(), parser_errposition(), PG_USED_FOR_ASSERTS_ONLY, SelectStmt::rarg, SetOperationStmt::rarg, TargetEntry::resjunk, rt_fetch, RangeTblRef::rtindex, select_common_collation(), select_common_type(), SETOP_INTERSECT, SETOP_NONE, SETOP_UNION, setup_parser_errposition_callback(), snprintf(), SelectStmt::sortClause, SortGroupClause::sortop, Query::targetList, SortGroupClause::tleSortGroupRef, SetToDefault::typeId, SetToDefault::typeMod, UNKNOWNOID, and SelectStmt::withClause.

Referenced by transformSetOperationStmt().

1804 {
1805  bool isLeaf;
1806 
1807  Assert(stmt && IsA(stmt, SelectStmt));
1808 
1809  /* Guard against stack overflow due to overly complex set-expressions */
1811 
1812  /*
1813  * Validity-check both leaf and internal SELECTs for disallowed ops.
1814  */
1815  if (stmt->intoClause)
1816  ereport(ERROR,
1817  (errcode(ERRCODE_SYNTAX_ERROR),
1818  errmsg("INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"),
1819  parser_errposition(pstate,
1820  exprLocation((Node *) stmt->intoClause))));
1821 
1822  /* We don't support FOR UPDATE/SHARE with set ops at the moment. */
1823  if (stmt->lockingClause)
1824  ereport(ERROR,
1825  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1826  /*------
1827  translator: %s is a SQL row locking clause such as FOR UPDATE */
1828  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
1830  linitial(stmt->lockingClause))->strength))));
1831 
1832  /*
1833  * If an internal node of a set-op tree has ORDER BY, LIMIT, FOR UPDATE,
1834  * or WITH clauses attached, we need to treat it like a leaf node to
1835  * generate an independent sub-Query tree. Otherwise, it can be
1836  * represented by a SetOperationStmt node underneath the parent Query.
1837  */
1838  if (stmt->op == SETOP_NONE)
1839  {
1840  Assert(stmt->larg == NULL && stmt->rarg == NULL);
1841  isLeaf = true;
1842  }
1843  else
1844  {
1845  Assert(stmt->larg != NULL && stmt->rarg != NULL);
1846  if (stmt->sortClause || stmt->limitOffset || stmt->limitCount ||
1847  stmt->lockingClause || stmt->withClause)
1848  isLeaf = true;
1849  else
1850  isLeaf = false;
1851  }
1852 
1853  if (isLeaf)
1854  {
1855  /* Process leaf SELECT */
1856  Query *selectQuery;
1857  char selectName[32];
1859  RangeTblRef *rtr;
1860  ListCell *tl;
1861 
1862  /*
1863  * Transform SelectStmt into a Query.
1864  *
1865  * This works the same as SELECT transformation normally would, except
1866  * that we prevent resolving unknown-type outputs as TEXT. This does
1867  * not change the subquery's semantics since if the column type
1868  * matters semantically, it would have been resolved to something else
1869  * anyway. Doing this lets us resolve such outputs using
1870  * select_common_type(), below.
1871  *
1872  * Note: previously transformed sub-queries don't affect the parsing
1873  * of this sub-query, because they are not in the toplevel pstate's
1874  * namespace list.
1875  */
1876  selectQuery = parse_sub_analyze((Node *) stmt, pstate,
1877  NULL, false, false);
1878 
1879  /*
1880  * Check for bogus references to Vars on the current query level (but
1881  * upper-level references are okay). Normally this can't happen
1882  * because the namespace will be empty, but it could happen if we are
1883  * inside a rule.
1884  */
1885  if (pstate->p_namespace)
1886  {
1887  if (contain_vars_of_level((Node *) selectQuery, 1))
1888  ereport(ERROR,
1889  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
1890  errmsg("UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level"),
1891  parser_errposition(pstate,
1892  locate_var_of_level((Node *) selectQuery, 1))));
1893  }
1894 
1895  /*
1896  * Extract a list of the non-junk TLEs for upper-level processing.
1897  */
1898  if (targetlist)
1899  {
1900  *targetlist = NIL;
1901  foreach(tl, selectQuery->targetList)
1902  {
1903  TargetEntry *tle = (TargetEntry *) lfirst(tl);
1904 
1905  if (!tle->resjunk)
1906  *targetlist = lappend(*targetlist, tle);
1907  }
1908  }
1909 
1910  /*
1911  * Make the leaf query be a subquery in the top-level rangetable.
1912  */
1913  snprintf(selectName, sizeof(selectName), "*SELECT* %d",
1914  list_length(pstate->p_rtable) + 1);
1915  rte = addRangeTableEntryForSubquery(pstate,
1916  selectQuery,
1917  makeAlias(selectName, NIL),
1918  false,
1919  false);
1920 
1921  /*
1922  * Return a RangeTblRef to replace the SelectStmt in the set-op tree.
1923  */
1924  rtr = makeNode(RangeTblRef);
1925  /* assume new rte is at end */
1926  rtr->rtindex = list_length(pstate->p_rtable);
1927  Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
1928  return (Node *) rtr;
1929  }
1930  else
1931  {
1932  /* Process an internal node (set operation node) */
1934  List *ltargetlist;
1935  List *rtargetlist;
1936  ListCell *ltl;
1937  ListCell *rtl;
1938  const char *context;
1939 
1940  context = (stmt->op == SETOP_UNION ? "UNION" :
1941  (stmt->op == SETOP_INTERSECT ? "INTERSECT" :
1942  "EXCEPT"));
1943 
1944  op->op = stmt->op;
1945  op->all = stmt->all;
1946 
1947  /*
1948  * Recursively transform the left child node.
1949  */
1950  op->larg = transformSetOperationTree(pstate, stmt->larg,
1951  false,
1952  &ltargetlist);
1953 
1954  /*
1955  * If we are processing a recursive union query, now is the time to
1956  * examine the non-recursive term's output columns and mark the
1957  * containing CTE as having those result columns. We should do this
1958  * only at the topmost setop of the CTE, of course.
1959  */
1960  if (isTopLevel &&
1961  pstate->p_parent_cte &&
1962  pstate->p_parent_cte->cterecursive)
1963  determineRecursiveColTypes(pstate, op->larg, ltargetlist);
1964 
1965  /*
1966  * Recursively transform the right child node.
1967  */
1968  op->rarg = transformSetOperationTree(pstate, stmt->rarg,
1969  false,
1970  &rtargetlist);
1971 
1972  /*
1973  * Verify that the two children have the same number of non-junk
1974  * columns, and determine the types of the merged output columns.
1975  */
1976  if (list_length(ltargetlist) != list_length(rtargetlist))
1977  ereport(ERROR,
1978  (errcode(ERRCODE_SYNTAX_ERROR),
1979  errmsg("each %s query must have the same number of columns",
1980  context),
1981  parser_errposition(pstate,
1982  exprLocation((Node *) rtargetlist))));
1983 
1984  if (targetlist)
1985  *targetlist = NIL;
1986  op->colTypes = NIL;
1987  op->colTypmods = NIL;
1988  op->colCollations = NIL;
1989  op->groupClauses = NIL;
1990  forboth(ltl, ltargetlist, rtl, rtargetlist)
1991  {
1992  TargetEntry *ltle = (TargetEntry *) lfirst(ltl);
1993  TargetEntry *rtle = (TargetEntry *) lfirst(rtl);
1994  Node *lcolnode = (Node *) ltle->expr;
1995  Node *rcolnode = (Node *) rtle->expr;
1996  Oid lcoltype = exprType(lcolnode);
1997  Oid rcoltype = exprType(rcolnode);
1998  int32 lcoltypmod = exprTypmod(lcolnode);
1999  int32 rcoltypmod = exprTypmod(rcolnode);
2000  Node *bestexpr;
2001  int bestlocation;
2002  Oid rescoltype;
2003  int32 rescoltypmod;
2004  Oid rescolcoll;
2005 
2006  /* select common type, same as CASE et al */
2007  rescoltype = select_common_type(pstate,
2008  list_make2(lcolnode, rcolnode),
2009  context,
2010  &bestexpr);
2011  bestlocation = exprLocation(bestexpr);
2012  /* if same type and same typmod, use typmod; else default */
2013  if (lcoltype == rcoltype && lcoltypmod == rcoltypmod)
2014  rescoltypmod = lcoltypmod;
2015  else
2016  rescoltypmod = -1;
2017 
2018  /*
2019  * Verify the coercions are actually possible. If not, we'd fail
2020  * later anyway, but we want to fail now while we have sufficient
2021  * context to produce an error cursor position.
2022  *
2023  * For all non-UNKNOWN-type cases, we verify coercibility but we
2024  * don't modify the child's expression, for fear of changing the
2025  * child query's semantics.
2026  *
2027  * If a child expression is an UNKNOWN-type Const or Param, we
2028  * want to replace it with the coerced expression. This can only
2029  * happen when the child is a leaf set-op node. It's safe to
2030  * replace the expression because if the child query's semantics
2031  * depended on the type of this output column, it'd have already
2032  * coerced the UNKNOWN to something else. We want to do this
2033  * because (a) we want to verify that a Const is valid for the
2034  * target type, or resolve the actual type of an UNKNOWN Param,
2035  * and (b) we want to avoid unnecessary discrepancies between the
2036  * output type of the child query and the resolved target type.
2037  * Such a discrepancy would disable optimization in the planner.
2038  *
2039  * If it's some other UNKNOWN-type node, eg a Var, we do nothing
2040  * (knowing that coerce_to_common_type would fail). The planner
2041  * is sometimes able to fold an UNKNOWN Var to a constant before
2042  * it has to coerce the type, so failing now would just break
2043  * cases that might work.
2044  */
2045  if (lcoltype != UNKNOWNOID)
2046  lcolnode = coerce_to_common_type(pstate, lcolnode,
2047  rescoltype, context);
2048  else if (IsA(lcolnode, Const) ||
2049  IsA(lcolnode, Param))
2050  {
2051  lcolnode = coerce_to_common_type(pstate, lcolnode,
2052  rescoltype, context);
2053  ltle->expr = (Expr *) lcolnode;
2054  }
2055 
2056  if (rcoltype != UNKNOWNOID)
2057  rcolnode = coerce_to_common_type(pstate, rcolnode,
2058  rescoltype, context);
2059  else if (IsA(rcolnode, Const) ||
2060  IsA(rcolnode, Param))
2061  {
2062  rcolnode = coerce_to_common_type(pstate, rcolnode,
2063  rescoltype, context);
2064  rtle->expr = (Expr *) rcolnode;
2065  }
2066 
2067  /*
2068  * Select common collation. A common collation is required for
2069  * all set operators except UNION ALL; see SQL:2008 7.13 <query
2070  * expression> Syntax Rule 15c. (If we fail to identify a common
2071  * collation for a UNION ALL column, the curCollations element
2072  * will be set to InvalidOid, which may result in a runtime error
2073  * if something at a higher query level wants to use the column's
2074  * collation.)
2075  */
2076  rescolcoll = select_common_collation(pstate,
2077  list_make2(lcolnode, rcolnode),
2078  (op->op == SETOP_UNION && op->all));
2079 
2080  /* emit results */
2081  op->colTypes = lappend_oid(op->colTypes, rescoltype);
2082  op->colTypmods = lappend_int(op->colTypmods, rescoltypmod);
2083  op->colCollations = lappend_oid(op->colCollations, rescolcoll);
2084 
2085  /*
2086  * For all cases except UNION ALL, identify the grouping operators
2087  * (and, if available, sorting operators) that will be used to
2088  * eliminate duplicates.
2089  */
2090  if (op->op != SETOP_UNION || !op->all)
2091  {
2093  Oid sortop;
2094  Oid eqop;
2095  bool hashable;
2096  ParseCallbackState pcbstate;
2097 
2098  setup_parser_errposition_callback(&pcbstate, pstate,
2099  bestlocation);
2100 
2101  /* determine the eqop and optional sortop */
2102  get_sort_group_operators(rescoltype,
2103  false, true, false,
2104  &sortop, &eqop, NULL,
2105  &hashable);
2106 
2108 
2109  /* we don't have a tlist yet, so can't assign sortgrouprefs */
2110  grpcl->tleSortGroupRef = 0;
2111  grpcl->eqop = eqop;
2112  grpcl->sortop = sortop;
2113  grpcl->nulls_first = false; /* OK with or without sortop */
2114  grpcl->hashable = hashable;
2115 
2116  op->groupClauses = lappend(op->groupClauses, grpcl);
2117  }
2118 
2119  /*
2120  * Construct a dummy tlist entry to return. We use a SetToDefault
2121  * node for the expression, since it carries exactly the fields
2122  * needed, but any other expression node type would do as well.
2123  */
2124  if (targetlist)
2125  {
2126  SetToDefault *rescolnode = makeNode(SetToDefault);
2127  TargetEntry *restle;
2128 
2129  rescolnode->typeId = rescoltype;
2130  rescolnode->typeMod = rescoltypmod;
2131  rescolnode->collation = rescolcoll;
2132  rescolnode->location = bestlocation;
2133  restle = makeTargetEntry((Expr *) rescolnode,
2134  0, /* no need to set resno */
2135  NULL,
2136  false);
2137  *targetlist = lappend(*targetlist, restle);
2138  }
2139  }
2140 
2141  return (Node *) op;
2142  }
2143 }
#define list_make2(x1, x2)
Definition: pg_list.h:140
#define NIL
Definition: pg_list.h:69
struct SelectStmt * larg
Definition: parsenodes.h:1568
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2625
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
IntoClause * intoClause
Definition: parsenodes.h:1535
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1186
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
Node * limitOffset
Definition: parsenodes.h:1558
Index tleSortGroupRef
Definition: parsenodes.h:1204
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
CommonTableExpr * p_parent_cte
Definition: parse_node.h:183
signed int int32
Definition: c.h:302
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:386
int locate_var_of_level(Node *node, int levelsup)
Definition: var.c:437
void cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
Definition: parse_node.c:161
bool resjunk
Definition: primnodes.h:1382
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
List * p_namespace
Definition: parse_node.h:178
int32 typeMod
Definition: primnodes.h:1264
List * sortClause
Definition: parsenodes.h:1557
void check_stack_depth(void)
Definition: postgres.c:3154
Oid select_common_collation(ParseState *pstate, List *exprs, bool none_ok)
#define ereport(elevel, rest)
Definition: elog.h:122
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
static Node * transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, bool isTopLevel, List **targetlist)
Definition: analyze.c:1802
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:237
List * lockingClause
Definition: parsenodes.h:1560
void setup_parser_errposition_callback(ParseCallbackState *pcbstate, ParseState *pstate, int location)
Definition: parse_node.c:145
List * lappend_int(List *list, int datum)
Definition: list.c:146
Node * coerce_to_common_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *context)
List * lappend(List *list, void *datum)
Definition: list.c:128
RangeTblEntry * addRangeTableEntryForSubquery(ParseState *pstate, Query *subquery, Alias *alias, bool lateral, bool inFromCl)
List * colCollations
Definition: parsenodes.h:1605
SetOperation op
Definition: parsenodes.h:1566
Query * parse_sub_analyze(Node *parseTree, ParseState *parentParseState, CommonTableExpr *parentCTE, bool locked_from_parent, bool resolve_unknowns)
Definition: analyze.c:164
#define makeNode(_type_)
Definition: nodes.h:561
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
void get_sort_group_operators(Oid argtype, bool needLT, bool needEQ, bool needGT, Oid *ltOpr, Oid *eqOpr, Oid *gtOpr, bool *isHashable)
Definition: parse_oper.c:187
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:369
Expr * expr
Definition: primnodes.h:1375
struct SelectStmt * rarg
Definition: parsenodes.h:1569
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
SetOperation op
Definition: parsenodes.h:1596
#define UNKNOWNOID
Definition: pg_type.h:431
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid select_common_type(ParseState *pstate, List *exprs, const char *context, Node **which_expr)
WithClause * withClause
Definition: parsenodes.h:1561
static void determineRecursiveColTypes(ParseState *pstate, Node *larg, List *nrtargetlist)
Definition: analyze.c:2150
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:123
Definition: pg_list.h:45
Node * limitCount
Definition: parsenodes.h:1559
List * p_rtable
Definition: parse_node.h:174

◆ transformStmt()

Query* transformStmt ( ParseState pstate,
Node parseTree 
)

Definition at line 254 of file analyze.c.

References Query::canSetTag, CMD_UTILITY, Query::commandType, makeNode, nodeTag, SelectStmt::op, QSRC_ORIGINAL, Query::querySource, SETOP_NONE, T_CallStmt, T_CreateTableAsStmt, T_DeclareCursorStmt, T_DeleteStmt, T_ExplainStmt, T_InsertStmt, T_SelectStmt, T_UpdateStmt, transformCallStmt(), transformCreateTableAsStmt(), transformDeclareCursorStmt(), transformDeleteStmt(), transformExplainStmt(), transformInsertStmt(), transformSelectStmt(), transformSetOperationStmt(), transformUpdateStmt(), transformValuesClause(), Query::utilityStmt, and SelectStmt::valuesLists.

Referenced by parse_sub_analyze(), transformCreateTableAsStmt(), transformDeclareCursorStmt(), transformInsertStmt(), transformOptionalSelectInto(), and transformRuleStmt().

255 {
256  Query *result;
257 
258  /*
259  * We apply RAW_EXPRESSION_COVERAGE_TEST testing to basic DML statements;
260  * we can't just run it on everything because raw_expression_tree_walker()
261  * doesn't claim to handle utility statements.
262  */
263 #ifdef RAW_EXPRESSION_COVERAGE_TEST
264  switch (nodeTag(parseTree))
265  {
266  case T_SelectStmt:
267  case T_InsertStmt:
268  case T_UpdateStmt:
269  case T_DeleteStmt:
270  (void) test_raw_expression_coverage(parseTree, NULL);
271  break;
272  default:
273  break;
274  }
275 #endif /* RAW_EXPRESSION_COVERAGE_TEST */
276 
277  switch (nodeTag(parseTree))
278  {
279  /*
280  * Optimizable statements
281  */
282  case T_InsertStmt:
283  result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
284  break;
285 
286  case T_DeleteStmt:
287  result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
288  break;
289 
290  case T_UpdateStmt:
291  result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
292  break;
293 
294  case T_SelectStmt:
295  {
296  SelectStmt *n = (SelectStmt *) parseTree;
297 
298  if (n->valuesLists)
299  result = transformValuesClause(pstate, n);
300  else if (n->op == SETOP_NONE)
301  result = transformSelectStmt(pstate, n);
302  else
303  result = transformSetOperationStmt(pstate, n);
304  }
305  break;
306 
307  /*
308  * Special cases
309  */
310  case T_DeclareCursorStmt:
311  result = transformDeclareCursorStmt(pstate,
312  (DeclareCursorStmt *) parseTree);
313  break;
314 
315  case T_ExplainStmt:
316  result = transformExplainStmt(pstate,
317  (ExplainStmt *) parseTree);
318  break;
319 
320  case T_CreateTableAsStmt:
321  result = transformCreateTableAsStmt(pstate,
322  (CreateTableAsStmt *) parseTree);
323  break;
324 
325  case T_CallStmt:
326  result = transformCallStmt(pstate,
327  (CallStmt *) parseTree);
328 
329  default:
330 
331  /*
332  * other statements don't require any transformation; just return
333  * the original parsetree with a Query node plastered on top.
334  */
335  result = makeNode(Query);
336  result->commandType = CMD_UTILITY;
337  result->utilityStmt = (Node *) parseTree;
338  break;
339  }
340 
341  /* Mark as original query until we learn differently */
342  result->querySource = QSRC_ORIGINAL;
343  result->canSetTag = true;
344 
345  return result;
346 }
static Query * transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
Definition: analyze.c:2511
static Query * transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
Definition: analyze.c:2401
static Query * transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
Definition: analyze.c:2206
static Query * transformValuesClause(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1323
Definition: nodes.h:513
Node * utilityStmt
Definition: parsenodes.h:118
static Query * transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
Definition: analyze.c:2487
static Query * transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1187
List * valuesLists
Definition: parsenodes.h:1551
static Query * transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
Definition: analyze.c:466
SetOperation op
Definition: parsenodes.h:1566
CmdType commandType
Definition: parsenodes.h:110
#define makeNode(_type_)
Definition: nodes.h:561
QuerySource querySource
Definition: parsenodes.h:112
bool canSetTag
Definition: parsenodes.h:116
static Query * transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
Definition: analyze.c:396
static Query * transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1561
#define nodeTag(nodeptr)
Definition: nodes.h:518
static Query * transformCallStmt(ParseState *pstate, CallStmt *stmt)
Definition: analyze.c:2588

◆ transformTopLevelStmt()

Query* transformTopLevelStmt ( ParseState pstate,
RawStmt parseTree 
)

Definition at line 191 of file analyze.c.

References RawStmt::stmt, Query::stmt_len, RawStmt::stmt_len, Query::stmt_location, RawStmt::stmt_location, and transformOptionalSelectInto().

Referenced by inline_function(), parse_analyze(), parse_analyze_varparams(), and pg_analyze_and_rewrite_params().

192 {
193  Query *result;
194 
195  /* We're at top level, so allow SELECT INTO */
196  result = transformOptionalSelectInto(pstate, parseTree->stmt);
197 
198  result->stmt_location = parseTree->stmt_location;
199  result->stmt_len = parseTree->stmt_len;
200 
201  return result;
202 }
int stmt_location
Definition: parsenodes.h:179
Node * stmt
Definition: parsenodes.h:1447
int stmt_len
Definition: parsenodes.h:1449
int stmt_location
Definition: parsenodes.h:1448
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:215
int stmt_len
Definition: parsenodes.h:180

◆ transformUpdateStmt()

static Query * transformUpdateStmt ( ParseState pstate,
UpdateStmt stmt 
)
static

Definition at line 2206 of file analyze.c.

References ACL_UPDATE, assign_query_collations(), CMD_UPDATE, Query::commandType, Query::cteList, EXPR_KIND_WHERE, UpdateStmt::fromClause, Query::hasModifyingCTE, Query::hasRecursive, Query::hasSubLinks, Query::hasTargetSRFs, RangeVar::inh, Query::jointree, llast, makeFromExpr(), makeNode, ParseState::p_hasModifyingCTE, ParseState::p_hasSubLinks, ParseState::p_hasTargetSRFs, ParseState::p_is_insert, ParseState::p_joinlist, ParseNamespaceItem::p_lateral_ok, ParseNamespaceItem::p_lateral_only, ParseState::p_namespace, ParseState::p_rtable, WithClause::recursive, UpdateStmt::relation, Query::resultRelation, Query::returningList, UpdateStmt::returningList, Query::rtable, setTargetTable(), Query::targetList, UpdateStmt::targetList, transformFromClause(), transformReturningList(), transformUpdateTargetList(), transformWhereClause(), transformWithClause(), UpdateStmt::whereClause, and UpdateStmt::withClause.

Referenced by transformStmt().

2207 {
2208  Query *qry = makeNode(Query);
2209  ParseNamespaceItem *nsitem;
2210  Node *qual;
2211 
2212  qry->commandType = CMD_UPDATE;
2213  pstate->p_is_insert = false;
2214 
2215  /* process the WITH clause independently of all else */
2216  if (stmt->withClause)
2217  {
2218  qry->hasRecursive = stmt->withClause->recursive;
2219  qry->cteList = transformWithClause(pstate, stmt->withClause);
2220  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
2221  }
2222 
2223  qry->resultRelation = setTargetTable(pstate, stmt->relation,
2224  stmt->relation->inh,
2225  true,
2226  ACL_UPDATE);
2227 
2228  /* grab the namespace item made by setTargetTable */
2229  nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
2230 
2231  /* subqueries in FROM cannot access the result relation */
2232  nsitem->p_lateral_only = true;
2233  nsitem->p_lateral_ok = false;
2234 
2235  /*
2236  * the FROM clause is non-standard SQL syntax. We used to be able to do
2237  * this with REPLACE in POSTQUEL so we keep the feature.
2238  */
2239  transformFromClause(pstate, stmt->fromClause);
2240 
2241  /* remaining clauses can reference the result relation normally */
2242  nsitem->p_lateral_only = false;
2243  nsitem->p_lateral_ok = true;
2244 
2245  qual = transformWhereClause(pstate, stmt->whereClause,
2246  EXPR_KIND_WHERE, "WHERE");
2247 
2248  qry->returningList = transformReturningList(pstate, stmt->returningList);
2249 
2250  /*
2251  * Now we are done with SELECT-like processing, and can get on with
2252  * transforming the target list to match the UPDATE target columns.
2253  */
2254  qry->targetList = transformUpdateTargetList(pstate, stmt->targetList);
2255 
2256  qry->rtable = pstate->p_rtable;
2257  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2258 
2259  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2260  qry->hasSubLinks = pstate->p_hasSubLinks;
2261 
2262  assign_query_collations(pstate, qry);
2263 
2264  return qry;
2265 }
List * fromClause
Definition: parsenodes.h:1500
bool p_hasSubLinks
Definition: parse_node.h:203
static List * transformUpdateTargetList(ParseState *pstate, List *targetList)
Definition: analyze.c:2272
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:284
FromExpr * jointree
Definition: parsenodes.h:136
int resultRelation
Definition: parsenodes.h:120
#define llast(l)
Definition: pg_list.h:131
bool p_hasTargetSRFs
Definition: parse_node.h:202
Definition: nodes.h:513
List * targetList
Definition: parsenodes.h:1498
static List * transformReturningList(ParseState *pstate, List *returningList)
Definition: analyze.c:2344
Node * whereClause
Definition: parsenodes.h:1499
List * targetList
Definition: parsenodes.h:138
bool hasRecursive
Definition: parsenodes.h:128
List * rtable
Definition: parsenodes.h:135
List * p_namespace
Definition: parse_node.h:178
bool recursive
Definition: parsenodes.h:1346
List * returningList
Definition: parsenodes.h:144
bool p_hasModifyingCTE
Definition: parse_node.h:204
bool inh
Definition: primnodes.h:69
#define ACL_UPDATE
Definition: parsenodes.h:74
void transformFromClause(ParseState *pstate, List *frmList)
Definition: parse_clause.c:119
int setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource, AclMode requiredPerms)
Definition: parse_clause.c:185
CmdType commandType
Definition: parsenodes.h:110
bool hasTargetSRFs
Definition: parsenodes.h:125
#define makeNode(_type_)
Definition: nodes.h:561
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
RangeVar * relation
Definition: parsenodes.h:1497
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
List * returningList
Definition: parsenodes.h:1501
List * cteList
Definition: parsenodes.h:133
bool hasSubLinks
Definition: parsenodes.h:126
void assign_query_collations(ParseState *pstate, Query *query)
bool p_is_insert
Definition: parse_node.h:186
List * p_joinlist
Definition: parse_node.h:176
bool hasModifyingCTE
Definition: parsenodes.h:129
WithClause * withClause
Definition: parsenodes.h:1502
List * p_rtable
Definition: parse_node.h:174

◆ transformUpdateTargetList()

static List * transformUpdateTargetList ( ParseState pstate,
List targetList 
)
static

Definition at line 2272 of file analyze.c.

References attnameAttNum(), bms_add_member(), elog, ereport, errcode(), errmsg(), ERROR, EXPR_KIND_UPDATE_SOURCE, FirstLowInvalidHeapAttributeNumber, ResTarget::indirection, InvalidAttrNumber, lfirst, lfirst_node, list_head(), lnext, ResTarget::location, ResTarget::name, NIL, ParseState::p_next_resno, ParseState::p_target_rangetblentry, ParseState::p_target_relation, parser_errposition(), RelationData::rd_rel, RelationGetRelationName, TargetEntry::resjunk, TargetEntry::resname, TargetEntry::resno, transformTargetList(), RangeTblEntry::updatedCols, and updateTargetListEntry().

Referenced by transformOnConflictClause(), and transformUpdateStmt().

2273 {
2274  List *tlist = NIL;
2275  RangeTblEntry *target_rte;
2276  ListCell *orig_tl;
2277  ListCell *tl;
2278 
2279  tlist = transformTargetList(pstate, origTlist,
2281 
2282  /* Prepare to assign non-conflicting resnos to resjunk attributes */
2283  if (pstate->p_next_resno <= pstate->p_target_relation->rd_rel->relnatts)
2284  pstate->p_next_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
2285 
2286  /* Prepare non-junk columns for assignment to target table */
2287  target_rte = pstate->p_target_rangetblentry;
2288  orig_tl = list_head(origTlist);
2289 
2290  foreach(tl, tlist)
2291  {
2292  TargetEntry *tle = (TargetEntry *) lfirst(tl);
2293  ResTarget *origTarget;
2294  int attrno;
2295 
2296  if (tle->resjunk)
2297  {
2298  /*
2299  * Resjunk nodes need no additional processing, but be sure they
2300  * have resnos that do not match any target columns; else rewriter
2301  * or planner might get confused. They don't need a resname
2302  * either.
2303  */
2304  tle->resno = (AttrNumber) pstate->p_next_resno++;
2305  tle->resname = NULL;
2306  continue;
2307  }
2308  if (orig_tl == NULL)
2309  elog(ERROR, "UPDATE target count mismatch --- internal error");
2310  origTarget = lfirst_node(ResTarget, orig_tl);
2311 
2312  attrno = attnameAttNum(pstate->p_target_relation,
2313  origTarget->name, true);
2314  if (attrno == InvalidAttrNumber)
2315  ereport(ERROR,
2316  (errcode(ERRCODE_UNDEFINED_COLUMN),
2317  errmsg("column \"%s\" of relation \"%s\" does not exist",
2318  origTarget->name,
2320  parser_errposition(pstate, origTarget->location)));
2321 
2322  updateTargetListEntry(pstate, tle, origTarget->name,
2323  attrno,
2324  origTarget->indirection,
2325  origTarget->location);
2326 
2327  /* Mark the target column as requiring update permissions */
2328  target_rte->updatedCols = bms_add_member(target_rte->updatedCols,
2330 
2331  orig_tl = lnext(orig_tl);
2332  }
2333  if (orig_tl != NULL)
2334  elog(ERROR, "UPDATE target count mismatch --- internal error");
2335 
2336  return tlist;
2337 }
List * indirection
Definition: parsenodes.h:440
#define NIL
Definition: pg_list.h:69
char * name
Definition: parsenodes.h:439
int errcode(int sqlerrcode)
Definition: elog.c:575
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
Form_pg_class rd_rel
Definition: rel.h:114
char * resname
Definition: primnodes.h:1377
int location
Definition: parsenodes.h:442
List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind)
Definition: parse_target.c:131
bool resjunk
Definition: primnodes.h:1382
#define ERROR
Definition: elog.h:43
#define lfirst_node(type, lc)
Definition: pg_list.h:109
AttrNumber resno
Definition: primnodes.h:1376
int p_next_resno
Definition: parse_node.h:189
#define RelationGetRelationName(relation)
Definition: rel.h:445
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
RangeTblEntry * p_target_rangetblentry
Definition: parse_node.h:185
Bitmapset * updatedCols
Definition: parsenodes.h:1071
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
#define lfirst(lc)
Definition: pg_list.h:106
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:742
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation p_target_relation
Definition: parse_node.h:184
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
void updateTargetListEntry(ParseState *pstate, TargetEntry *tle, char *colname, int attrno, List *indirection, int location)
Definition: parse_target.c:617
int16 AttrNumber
Definition: attnum.h:21

◆ transformValuesClause()

static Query * transformValuesClause ( ParseState pstate,
SelectStmt stmt 
)
static

Definition at line 1323 of file analyze.c.

References addRangeTableEntryForValues(), addRTEtoQuery(), Assert, assign_query_collations(), CMD_SELECT, coerce_to_common_type(), Query::commandType, contain_vars_of_level(), Query::cteList, SelectStmt::distinctClause, ereport, errcode(), errmsg(), ERROR, expandRelAttrs(), EXPR_KIND_LIMIT, EXPR_KIND_OFFSET, EXPR_KIND_ORDER_BY, EXPR_KIND_VALUES, exprLocation(), exprTypmod(), forboth, SelectStmt::fromClause, SelectStmt::groupClause, Query::hasModifyingCTE, Query::hasRecursive, Query::hasSubLinks, SelectStmt::havingClause, i, SelectStmt::intoClause, Query::jointree, lappend(), lappend_int(), lappend_oid(), LCS_asString(), lfirst, Query::limitCount, SelectStmt::limitCount, Query::limitOffset, SelectStmt::limitOffset, linitial, list_free(), list_length(), list_make1, SelectStmt::lockingClause, makeFromExpr(), makeNode, NIL, SelectStmt::op, ParseState::p_hasModifyingCTE, ParseState::p_hasSubLinks, ParseState::p_joinlist, ParseState::p_next_resno, ParseState::p_rtable, palloc0(), parser_errposition(), WithClause::recursive, rt_fetch, Query::rtable, select_common_collation(), select_common_type(), SETOP_NONE, Query::sortClause, SelectStmt::sortClause, Query::targetList, SelectStmt::targetList, transformExpressionList(), transformLimitClause(), transformSortClause(), transformWithClause(), SelectStmt::valuesLists, SelectStmt::whereClause, SelectStmt::windowClause, and SelectStmt::withClause.

Referenced by transformStmt().

1324 {
1325  Query *qry = makeNode(Query);
1326  List *exprsLists;
1327  List *coltypes = NIL;
1328  List *coltypmods = NIL;
1329  List *colcollations = NIL;
1330  List **colexprs = NULL;
1331  int sublist_length = -1;
1332  bool lateral = false;
1333  RangeTblEntry *rte;
1334  int rtindex;
1335  ListCell *lc;
1336  ListCell *lc2;
1337  int i;
1338 
1339  qry->commandType = CMD_SELECT;
1340 
1341  /* Most SELECT stuff doesn't apply in a VALUES clause */
1342  Assert(stmt->distinctClause == NIL);
1343  Assert(stmt->intoClause == NULL);
1344  Assert(stmt->targetList == NIL);
1345  Assert(stmt->fromClause == NIL);
1346  Assert(stmt->whereClause == NULL);
1347  Assert(stmt->groupClause == NIL);
1348  Assert(stmt->havingClause == NULL);
1349  Assert(stmt->windowClause == NIL);
1350  Assert(stmt->op == SETOP_NONE);
1351 
1352  /* process the WITH clause independently of all else */
1353  if (stmt->withClause)
1354  {
1355  qry->hasRecursive = stmt->withClause->recursive;
1356  qry->cteList = transformWithClause(pstate, stmt->withClause);
1357  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1358  }
1359 
1360  /*
1361  * For each row of VALUES, transform the raw expressions.
1362  *
1363  * Note that the intermediate representation we build is column-organized
1364  * not row-organized. That simplifies the type and collation processing
1365  * below.
1366  */
1367  foreach(lc, stmt->valuesLists)
1368  {
1369  List *sublist = (List *) lfirst(lc);
1370 
1371  /*
1372  * Do basic expression transformation (same as a ROW() expr, but here
1373  * we disallow SetToDefault)
1374  */
1375  sublist = transformExpressionList(pstate, sublist,
1376  EXPR_KIND_VALUES, false);
1377 
1378  /*
1379  * All the sublists must be the same length, *after* transformation
1380  * (which might expand '*' into multiple items). The VALUES RTE can't
1381  * handle anything different.
1382  */
1383  if (sublist_length < 0)
1384  {
1385  /* Remember post-transformation length of first sublist */
1386  sublist_length = list_length(sublist);
1387  /* and allocate array for per-column lists */
1388  colexprs = (List **) palloc0(sublist_length * sizeof(List *));
1389  }
1390  else if (sublist_length != list_length(sublist))
1391  {
1392  ereport(ERROR,
1393  (errcode(ERRCODE_SYNTAX_ERROR),
1394  errmsg("VALUES lists must all be the same length"),
1395  parser_errposition(pstate,
1396  exprLocation((Node *) sublist))));
1397  }
1398 
1399  /* Build per-column expression lists */
1400  i = 0;
1401  foreach(lc2, sublist)
1402  {
1403  Node *col = (Node *) lfirst(lc2);
1404 
1405  colexprs[i] = lappend(colexprs[i], col);
1406  i++;
1407  }
1408 
1409  /* Release sub-list's cells to save memory */
1410  list_free(sublist);
1411  }
1412 
1413  /*
1414  * Now resolve the common types of the columns, and coerce everything to
1415  * those types. Then identify the common typmod and common collation, if
1416  * any, of each column.
1417  *
1418  * We must do collation processing now because (1) assign_query_collations
1419  * doesn't process rangetable entries, and (2) we need to label the VALUES
1420  * RTE with column collations for use in the outer query. We don't
1421  * consider conflict of implicit collations to be an error here; instead
1422  * the column will just show InvalidOid as its collation, and you'll get a
1423  * failure later if that results in failure to resolve a collation.
1424  *
1425  * Note we modify the per-column expression lists in-place.
1426  */
1427  for (i = 0; i < sublist_length; i++)
1428  {
1429  Oid coltype;
1430  int32 coltypmod = -1;
1431  Oid colcoll;
1432  bool first = true;
1433 
1434  coltype = select_common_type(pstate, colexprs[i], "VALUES", NULL);
1435 
1436  foreach(lc, colexprs[i])
1437  {
1438  Node *col = (Node *) lfirst(lc);
1439 
1440  col = coerce_to_common_type(pstate, col, coltype, "VALUES");
1441  lfirst(lc) = (void *) col;
1442  if (first)
1443  {
1444  coltypmod = exprTypmod(col);
1445  first = false;
1446  }
1447  else
1448  {
1449  /* As soon as we see a non-matching typmod, fall back to -1 */
1450  if (coltypmod >= 0 && coltypmod != exprTypmod(col))
1451  coltypmod = -1;
1452  }
1453  }
1454 
1455  colcoll = select_common_collation(pstate, colexprs[i], true);
1456 
1457  coltypes = lappend_oid(coltypes, coltype);
1458  coltypmods = lappend_int(coltypmods, coltypmod);
1459  colcollations = lappend_oid(colcollations, colcoll);
1460  }
1461 
1462  /*
1463  * Finally, rearrange the coerced expressions into row-organized lists.
1464  */
1465  exprsLists = NIL;
1466  foreach(lc, colexprs[0])
1467  {
1468  Node *col = (Node *) lfirst(lc);
1469  List *sublist;
1470 
1471  sublist = list_make1(col);
1472  exprsLists = lappend(exprsLists, sublist);
1473  }
1474  list_free(colexprs[0]);
1475  for (i = 1; i < sublist_length; i++)
1476  {
1477  forboth(lc, colexprs[i], lc2, exprsLists)
1478  {
1479  Node *col = (Node *) lfirst(lc);
1480  List *sublist = lfirst(lc2);
1481 
1482  /* sublist pointer in exprsLists won't need adjustment */
1483  (void) lappend(sublist, col);
1484  }
1485  list_free(colexprs[i]);
1486  }
1487 
1488  /*
1489  * Ordinarily there can't be any current-level Vars in the expression
1490  * lists, because the namespace was empty ... but if we're inside CREATE
1491  * RULE, then NEW/OLD references might appear. In that case we have to
1492  * mark the VALUES RTE as LATERAL.
1493  */
1494  if (pstate->p_rtable != NIL &&
1495  contain_vars_of_level((Node *) exprsLists, 0))
1496  lateral = true;
1497 
1498  /*
1499  * Generate the VALUES RTE
1500  */
1501  rte = addRangeTableEntryForValues(pstate, exprsLists,
1502  coltypes, coltypmods, colcollations,
1503  NULL, lateral, true);
1504  addRTEtoQuery(pstate, rte, true, true, true);
1505 
1506  /* assume new rte is at end */
1507  rtindex = list_length(pstate->p_rtable);
1508  Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
1509 
1510  /*
1511  * Generate a targetlist as though expanding "*"
1512  */
1513  Assert(pstate->p_next_resno == 1);
1514  qry->targetList = expandRelAttrs(pstate, rte, rtindex, 0, -1);
1515 
1516  /*
1517  * The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE to a
1518  * VALUES, so cope.
1519  */
1520  qry->sortClause = transformSortClause(pstate,
1521  stmt->sortClause,
1522  &qry->targetList,
1524  false /* allow SQL92 rules */ );
1525 
1526  qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
1527  EXPR_KIND_OFFSET, "OFFSET");
1528  qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
1529  EXPR_KIND_LIMIT, "LIMIT");
1530 
1531  if (stmt->lockingClause)
1532  ereport(ERROR,
1533  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1534  /*------
1535  translator: %s is a SQL row locking clause such as FOR UPDATE */
1536  errmsg("%s cannot be applied to VALUES",
1538  linitial(stmt->lockingClause))->strength))));
1539 
1540  qry->rtable = pstate->p_rtable;
1541  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
1542 
1543  qry->hasSubLinks = pstate->p_hasSubLinks;
1544 
1545  assign_query_collations(pstate, qry);
1546 
1547  return qry;
1548 }
Node * limitOffset
Definition: parsenodes.h:158
#define NIL
Definition: pg_list.h:69
bool p_hasSubLinks
Definition: parse_node.h:203
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:284
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2625
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
List * sortClause
Definition: parsenodes.h:156
IntoClause * intoClause
Definition: parsenodes.h:1535
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1186
List * fromClause
Definition: parsenodes.h:1537
FromExpr * jointree
Definition: parsenodes.h:136
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
List * transformSortClause(ParseState *pstate, List *orderlist, List **targetlist, ParseExprKind exprKind, bool useSQL99)
Node * limitOffset
Definition: parsenodes.h:1558
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
Node * transformLimitClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
signed int int32
Definition: c.h:302
List * targetList
Definition: parsenodes.h:138
bool hasRecursive
Definition: parsenodes.h:128
#define list_make1(x1)
Definition: pg_list.h:139
List * distinctClause
Definition: parsenodes.h:1533
#define linitial(l)
Definition: pg_list.h:111
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
Node * limitCount
Definition: parsenodes.h:159
List * sortClause
Definition: parsenodes.h:1557
List * targetList
Definition: parsenodes.h:1536
Oid select_common_collation(ParseState *pstate, List *exprs, bool none_ok)
int p_next_resno
Definition: parse_node.h:189
bool recursive
Definition: parsenodes.h:1346
List * valuesLists
Definition: parsenodes.h:1551
List * expandRelAttrs(ParseState *pstate, RangeTblEntry *rte, int rtindex, int sublevels_up, int location)
#define ereport(elevel, rest)
Definition: elog.h:122
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
List * lockingClause
Definition: parsenodes.h:1560
bool p_hasModifyingCTE
Definition: parse_node.h:204
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
List * lappend_int(List *list, int datum)
Definition: list.c:146
Node * coerce_to_common_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *context)
List * lappend(List *list, void *datum)
Definition: list.c:128
void * palloc0(Size size)
Definition: mcxt.c:864
List * transformExpressionList(ParseState *pstate, List *exprlist, ParseExprKind exprKind, bool allowDefault)
Definition: parse_target.c:228
List * windowClause
Definition: parsenodes.h:1541
SetOperation op
Definition: parsenodes.h:1566
CmdType commandType
Definition: parsenodes.h:110
#define makeNode(_type_)
Definition: nodes.h:561
RangeTblEntry * addRangeTableEntryForValues(ParseState *pstate, List *exprs, List *coltypes, List *coltypmods, List *colcollations, Alias *alias, bool lateral, bool inFromCl)
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:369
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
List * groupClause
Definition: parsenodes.h:1539
List * cteList
Definition: parsenodes.h:133
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool hasSubLinks
Definition: parsenodes.h:126
void assign_query_collations(ParseState *pstate, Query *query)
Node * havingClause
Definition: parsenodes.h:1540
void list_free(List *list)
Definition: list.c:1133
int i
List * p_joinlist
Definition: parse_node.h:176
bool hasModifyingCTE
Definition: parsenodes.h:129
Oid select_common_type(ParseState *pstate, List *exprs, const char *context, Node **which_expr)
WithClause * withClause
Definition: parsenodes.h:1561
Definition: pg_list.h:45
Node * limitCount
Definition: parsenodes.h:1559
Node * whereClause
Definition: parsenodes.h:1538
List * p_rtable
Definition: parse_node.h:174

Variable Documentation

◆ post_parse_analyze_hook

post_parse_analyze_hook_type post_parse_analyze_hook = NULL