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 357 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().

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

◆ applyLockingClause()

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

Definition at line 2879 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().

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

◆ CheckSelectLocking()

void CheckSelectLocking ( Query qry,
LockClauseStrength  strength 
)

Definition at line 2644 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().

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

◆ count_rowexpr_columns()

static int count_rowexpr_columns ( ParseState pstate,
Node expr 
)
static

Definition at line 1139 of file analyze.c.

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

Referenced by transformInsertRow().

1140 {
1141  if (expr == NULL)
1142  return -1;
1143  if (IsA(expr, RowExpr))
1144  return list_length(((RowExpr *) expr)->args);
1145  if (IsA(expr, Var))
1146  {
1147  Var *var = (Var *) expr;
1148  AttrNumber attnum = var->varattno;
1149 
1150  if (attnum > 0 && var->vartype == RECORDOID)
1151  {
1152  RangeTblEntry *rte;
1153 
1154  rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup);
1155  if (rte->rtekind == RTE_SUBQUERY)
1156  {
1157  /* Subselect-in-FROM: examine sub-select's output expr */
1159  attnum);
1160 
1161  if (ste == NULL || ste->resjunk)
1162  return -1;
1163  expr = (Node *) ste->expr;
1164  if (IsA(expr, RowExpr))
1165  return list_length(((RowExpr *) expr)->args);
1166  }
1167  }
1168  }
1169  return -1;
1170 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
Index varlevelsup
Definition: primnodes.h:173
Definition: nodes.h:516
AttrNumber varattno
Definition: primnodes.h:168
Definition: primnodes.h:163
List * targetList
Definition: parsenodes.h:140
bool resjunk
Definition: primnodes.h:1382
Oid vartype
Definition: primnodes.h:170
Index varno
Definition: primnodes.h:166
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
int16 attnum
Definition: pg_attribute.h:79
Expr * expr
Definition: primnodes.h:1375
static int list_length(const List *l)
Definition: pg_list.h:89
RTEKind rtekind
Definition: parsenodes.h:962
Query * subquery
Definition: parsenodes.h:985
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 2144 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().

2145 {
2146  Node *node;
2147  int leftmostRTI;
2148  Query *leftmostQuery;
2149  List *targetList;
2150  ListCell *left_tlist;
2151  ListCell *nrtl;
2152  int next_resno;
2153 
2154  /*
2155  * Find leftmost leaf SELECT
2156  */
2157  node = larg;
2158  while (node && IsA(node, SetOperationStmt))
2159  node = ((SetOperationStmt *) node)->larg;
2160  Assert(node && IsA(node, RangeTblRef));
2161  leftmostRTI = ((RangeTblRef *) node)->rtindex;
2162  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2163  Assert(leftmostQuery != NULL);
2164 
2165  /*
2166  * Generate dummy targetlist using column names of leftmost select and
2167  * dummy result expressions of the non-recursive term.
2168  */
2169  targetList = NIL;
2170  left_tlist = list_head(leftmostQuery->targetList);
2171  next_resno = 1;
2172 
2173  foreach(nrtl, nrtargetlist)
2174  {
2175  TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
2176  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
2177  char *colName;
2178  TargetEntry *tle;
2179 
2180  Assert(!lefttle->resjunk);
2181  colName = pstrdup(lefttle->resname);
2182  tle = makeTargetEntry(nrtle->expr,
2183  next_resno++,
2184  colName,
2185  false);
2186  targetList = lappend(targetList, tle);
2187  left_tlist = lnext(left_tlist);
2188  }
2189 
2190  /* Now build CTE's output column info using dummy targetlist */
2191  analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
2192 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
void analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
Definition: parse_cte.c:352
char * pstrdup(const char *in)
Definition: mcxt.c:1161
Definition: nodes.h:516
char * resname
Definition: primnodes.h:1377
CommonTableExpr * p_parent_cte
Definition: parse_node.h:183
List * targetList
Definition: parsenodes.h:140
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:699
#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 2619 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().

2620 {
2621  switch (strength)
2622  {
2623  case LCS_NONE:
2624  Assert(false);
2625  break;
2626  case LCS_FORKEYSHARE:
2627  return "FOR KEY SHARE";
2628  case LCS_FORSHARE:
2629  return "FOR SHARE";
2630  case LCS_FORNOKEYUPDATE:
2631  return "FOR NO KEY UPDATE";
2632  case LCS_FORUPDATE:
2633  return "FOR UPDATE";
2634  }
2635  return "FOR some"; /* shouldn't happen */
2636 }
#define Assert(condition)
Definition: c.h:699

◆ 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:699
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:699
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 2582 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().

2583 {
2584  List *targs;
2585  ListCell *lc;
2586  Node *node;
2587  Query *result;
2588 
2589  targs = NIL;
2590  foreach(lc, stmt->funccall->args)
2591  {
2592  targs = lappend(targs, transformExpr(pstate,
2593  (Node *) lfirst(lc),
2595  }
2596 
2597  node = ParseFuncOrColumn(pstate,
2598  stmt->funccall->funcname,
2599  targs,
2600  pstate->p_last_srf,
2601  stmt->funccall,
2602  true,
2603  stmt->funccall->location);
2604 
2605  stmt->funcexpr = castNode(FuncExpr, node);
2606 
2607  result = makeNode(Query);
2608  result->commandType = CMD_UTILITY;
2609  result->utilityStmt = (Node *) stmt;
2610 
2611  return result;
2612 }
#define NIL
Definition: pg_list.h:69
FuncExpr * funcexpr
Definition: parsenodes.h:2827
#define castNode(_type_, nodeptr)
Definition: nodes.h:585
FuncCall * funccall
Definition: parsenodes.h:2826
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:146
Definition: nodes.h:516
int location
Definition: parsenodes.h:360
Node * utilityStmt
Definition: parsenodes.h:120
Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *last_srf, FuncCall *fn, bool proc_call, int location)
Definition: parse_func.c:78
List * lappend(List *list, void *datum)
Definition: list.c:128
Node * p_last_srf
Definition: parse_node.h:206
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:564
#define lfirst(lc)
Definition: pg_list.h:106
List * args
Definition: parsenodes.h:352
List * funcname
Definition: parsenodes.h:351
Definition: pg_list.h:45

◆ transformCreateTableAsStmt()

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

Definition at line 2505 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, transformStmt(), Query::utilityStmt, and IntoClause::viewQuery.

Referenced by transformStmt().

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

◆ transformDeclareCursorStmt()

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

Definition at line 2395 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().

2396 {
2397  Query *result;
2398  Query *query;
2399 
2400  /*
2401  * Don't allow both SCROLL and NO SCROLL to be specified
2402  */
2403  if ((stmt->options & CURSOR_OPT_SCROLL) &&
2404  (stmt->options & CURSOR_OPT_NO_SCROLL))
2405  ereport(ERROR,
2406  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2407  errmsg("cannot specify both SCROLL and NO SCROLL")));
2408 
2409  /* Transform contained query, not allowing SELECT INTO */
2410  query = transformStmt(pstate, stmt->query);
2411  stmt->query = (Node *) query;
2412 
2413  /* Grammar should not have allowed anything but SELECT */
2414  if (!IsA(query, Query) ||
2415  query->commandType != CMD_SELECT)
2416  elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR");
2417 
2418  /*
2419  * We also disallow data-modifying WITH in a cursor. (This could be
2420  * allowed, but the semantics of when the updates occur might be
2421  * surprising.)
2422  */
2423  if (query->hasModifyingCTE)
2424  ereport(ERROR,
2425  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2426  errmsg("DECLARE CURSOR must not contain data-modifying statements in WITH")));
2427 
2428  /* FOR UPDATE and WITH HOLD are not compatible */
2429  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
2430  ereport(ERROR,
2431  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2432  /*------
2433  translator: %s is a SQL row locking clause such as FOR UPDATE */
2434  errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
2436  linitial(query->rowMarks))->strength)),
2437  errdetail("Holdable cursors must be READ ONLY.")));
2438 
2439  /* FOR UPDATE and SCROLL are not compatible */
2440  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
2441  ereport(ERROR,
2442  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2443  /*------
2444  translator: %s is a SQL row locking clause such as FOR UPDATE */
2445  errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
2447  linitial(query->rowMarks))->strength)),
2448  errdetail("Scrollable cursors must be READ ONLY.")));
2449 
2450  /* FOR UPDATE and INSENSITIVE are not compatible */
2451  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
2452  ereport(ERROR,
2453  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2454  /*------
2455  translator: %s is a SQL row locking clause such as FOR UPDATE */
2456  errmsg("DECLARE INSENSITIVE CURSOR ... %s is not supported",
2458  linitial(query->rowMarks))->strength)),
2459  errdetail("Insensitive cursors must be READ ONLY.")));
2460 
2461  /* represent the command as a utility Query */
2462  result = makeNode(Query);
2463  result->commandType = CMD_UTILITY;
2464  result->utilityStmt = (Node *) stmt;
2465 
2466  return result;
2467 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2619
#define CURSOR_OPT_HOLD
Definition: parsenodes.h:2648
Definition: nodes.h:516
int errcode(int sqlerrcode)
Definition: elog.c:575
#define CURSOR_OPT_INSENSITIVE
Definition: parsenodes.h:2647
List * rowMarks
Definition: parsenodes.h:163
Node * utilityStmt
Definition: parsenodes.h:120
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:2646
#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:112
#define makeNode(_type_)
Definition: nodes.h:564
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2645
bool hasModifyingCTE
Definition: parsenodes.h:131
#define elog
Definition: elog.h:219

◆ transformDeleteStmt()

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

Definition at line 397 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().

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

◆ transformExplainStmt()

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

Definition at line 2481 of file analyze.c.

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

Referenced by transformStmt().

2482 {
2483  Query *result;
2484 
2485  /* transform contained query, allowing SELECT INTO */
2486  stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
2487 
2488  /* represent the command as a utility Query */
2489  result = makeNode(Query);
2490  result->commandType = CMD_UTILITY;
2491  result->utilityStmt = (Node *) stmt;
2492 
2493  return result;
2494 }
Definition: nodes.h:516
Node * utilityStmt
Definition: parsenodes.h:120
Node * query
Definition: parsenodes.h:3176
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:564
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 900 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().

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

Referenced by transformStmt().

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

◆ transformLockingClause()

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

Definition at line 2708 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().

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

◆ transformOnConflictClause()

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

Definition at line 1004 of file analyze.c.

References OnConflictClause::action, OnConflictExpr::action, addRangeTableEntryForRelation(), addRTEtoQuery(), OnConflictExpr::arbiterElems, OnConflictExpr::arbiterWhere, OnConflictExpr::constraint, OnConflictExpr::exclRelIndex, OnConflictExpr::exclRelTlist, EXPR_KIND_WHERE, 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_rel, RelationGetNumberOfAttributes, RangeTblEntry::relkind, OnConflictClause::targetList, transformOnConflictArbiter(), transformUpdateTargetList(), transformWhereClause(), TupleDescAttr, and OnConflictClause::whereClause.

Referenced by transformInsertStmt().

1006 {
1007  List *arbiterElems;
1008  Node *arbiterWhere;
1009  Oid arbiterConstraint;
1010  List *onConflictSet = NIL;
1011  Node *onConflictWhere = NULL;
1012  RangeTblEntry *exclRte = NULL;
1013  int exclRelIndex = 0;
1014  List *exclRelTlist = NIL;
1015  OnConflictExpr *result;
1016 
1017  /* Process the arbiter clause, ON CONFLICT ON (...) */
1018  transformOnConflictArbiter(pstate, onConflictClause, &arbiterElems,
1019  &arbiterWhere, &arbiterConstraint);
1020 
1021  /* Process DO UPDATE */
1022  if (onConflictClause->action == ONCONFLICT_UPDATE)
1023  {
1024  Relation targetrel = pstate->p_target_relation;
1025  Var *var;
1026  TargetEntry *te;
1027  int attno;
1028 
1029  /*
1030  * All INSERT expressions have been parsed, get ready for potentially
1031  * existing SET statements that need to be processed like an UPDATE.
1032  */
1033  pstate->p_is_insert = false;
1034 
1035  /*
1036  * Add range table entry for the EXCLUDED pseudo relation; relkind is
1037  * set to composite to signal that we're not dealing with an actual
1038  * relation.
1039  */
1040  exclRte = addRangeTableEntryForRelation(pstate,
1041  targetrel,
1042  makeAlias("excluded", NIL),
1043  false, false);
1044  exclRte->relkind = RELKIND_COMPOSITE_TYPE;
1045  exclRelIndex = list_length(pstate->p_rtable);
1046 
1047  /*
1048  * Build a targetlist representing the columns of the EXCLUDED pseudo
1049  * relation. Have to be careful to use resnos that correspond to
1050  * attnos of the underlying relation.
1051  */
1052  for (attno = 0; attno < RelationGetNumberOfAttributes(targetrel); attno++)
1053  {
1054  Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno);
1055  char *name;
1056 
1057  if (attr->attisdropped)
1058  {
1059  /*
1060  * can't use atttypid here, but it doesn't really matter what
1061  * type the Const claims to be.
1062  */
1063  var = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
1064  name = "";
1065  }
1066  else
1067  {
1068  var = makeVar(exclRelIndex, attno + 1,
1069  attr->atttypid, attr->atttypmod,
1070  attr->attcollation,
1071  0);
1072  name = pstrdup(NameStr(attr->attname));
1073  }
1074 
1075  te = makeTargetEntry((Expr *) var,
1076  attno + 1,
1077  name,
1078  false);
1079 
1080  /* don't require select access yet */
1081  exclRelTlist = lappend(exclRelTlist, te);
1082  }
1083 
1084  /*
1085  * Add a whole-row-Var entry to support references to "EXCLUDED.*".
1086  * Like the other entries in exclRelTlist, its resno must match the
1087  * Var's varattno, else the wrong things happen while resolving
1088  * references in setrefs.c. This is against normal conventions for
1089  * targetlists, but it's okay since we don't use this as a real tlist.
1090  */
1091  var = makeVar(exclRelIndex, InvalidAttrNumber,
1092  targetrel->rd_rel->reltype,
1093  -1, InvalidOid, 0);
1094  te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
1095  exclRelTlist = lappend(exclRelTlist, te);
1096 
1097  /*
1098  * Add EXCLUDED and the target RTE to the namespace, so that they can
1099  * be used in the UPDATE statement.
1100  */
1101  addRTEtoQuery(pstate, exclRte, false, true, true);
1102  addRTEtoQuery(pstate, pstate->p_target_rangetblentry,
1103  false, true, true);
1104 
1105  onConflictSet =
1106  transformUpdateTargetList(pstate, onConflictClause->targetList);
1107 
1108  onConflictWhere = transformWhereClause(pstate,
1109  onConflictClause->whereClause,
1110  EXPR_KIND_WHERE, "WHERE");
1111  }
1112 
1113  /* Finally, build ON CONFLICT DO [NOTHING | UPDATE] expression */
1114  result = makeNode(OnConflictExpr);
1115 
1116  result->action = onConflictClause->action;
1117  result->arbiterElems = arbiterElems;
1118  result->arbiterWhere = arbiterWhere;
1119  result->constraint = arbiterConstraint;
1120  result->onConflictSet = onConflictSet;
1121  result->onConflictWhere = onConflictWhere;
1122  result->exclRelIndex = exclRelIndex;
1123  result->exclRelTlist = exclRelTlist;
1124 
1125  return result;
1126 }
#define NIL
Definition: pg_list.h:69
static List * transformUpdateTargetList(ParseState *pstate, List *targetList)
Definition: analyze.c:2266
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:413
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
char * pstrdup(const char *in)
Definition: mcxt.c:1161
Definition: nodes.h:516
void transformOnConflictArbiter(ParseState *pstate, OnConflictClause *onConflictClause, List **arbiterExpr, Node **arbiterWhere, Oid *constraint)
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:163
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
List * exclRelTlist
Definition: primnodes.h:1506
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
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:85
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:564
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
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:576
Node * onConflictWhere
Definition: primnodes.h:1504
OnConflictAction action
Definition: parsenodes.h:1377
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:1571
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
IntoClause * intoClause
Definition: parsenodes.h:1538
Definition: nodes.h:516
ObjectType relkind
Definition: parsenodes.h:3198
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:254
SetOperation op
Definition: parsenodes.h:1569
IntoClause * into
Definition: parsenodes.h:3197
#define makeNode(_type_)
Definition: nodes.h:564
#define Assert(condition)
Definition: c.h:699

◆ transformReturningList()

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

Definition at line 2338 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().

2339 {
2340  List *rlist;
2341  int save_next_resno;
2342 
2343  if (returningList == NIL)
2344  return NIL; /* nothing to do */
2345 
2346  /*
2347  * We need to assign resnos starting at one in the RETURNING list. Save
2348  * and restore the main tlist's value of p_next_resno, just in case
2349  * someone looks at it later (probably won't happen).
2350  */
2351  save_next_resno = pstate->p_next_resno;
2352  pstate->p_next_resno = 1;
2353 
2354  /* transform RETURNING identically to a SELECT targetlist */
2355  rlist = transformTargetList(pstate, returningList, EXPR_KIND_RETURNING);
2356 
2357  /*
2358  * Complain if the nonempty tlist expanded to nothing (which is possible
2359  * if it contains only a star-expansion of a zero-column table). If we
2360  * allow this, the parsed Query will look like it didn't have RETURNING,
2361  * with results that would probably surprise the user.
2362  */
2363  if (rlist == NIL)
2364  ereport(ERROR,
2365  (errcode(ERRCODE_SYNTAX_ERROR),
2366  errmsg("RETURNING must have at least one column"),
2367  parser_errposition(pstate,
2368  exprLocation(linitial(returningList)))));
2369 
2370  /* mark column origins */
2371  markTargetListOrigins(pstate, rlist);
2372 
2373  /* resolve any still-unresolved output columns as being type text */
2374  if (pstate->p_resolve_unknowns)
2375  resolveTargetListUnknowns(pstate, rlist);
2376 
2377  /* restore state */
2378  pstate->p_next_resno = save_next_resno;
2379 
2380  return rlist;
2381 }
#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 1181 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().

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

◆ transformSetOperationStmt()

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

Definition at line 1555 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().

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

Referenced by transformSetOperationStmt().

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

◆ 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:181
Node * stmt
Definition: parsenodes.h:1450
int stmt_len
Definition: parsenodes.h:1452
int stmt_location
Definition: parsenodes.h:1451
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:215
int stmt_len
Definition: parsenodes.h:182

◆ transformUpdateStmt()

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

Definition at line 2200 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().

2201 {
2202  Query *qry = makeNode(Query);
2203  ParseNamespaceItem *nsitem;
2204  Node *qual;
2205 
2206  qry->commandType = CMD_UPDATE;
2207  pstate->p_is_insert = false;
2208 
2209  /* process the WITH clause independently of all else */
2210  if (stmt->withClause)
2211  {
2212  qry->hasRecursive = stmt->withClause->recursive;
2213  qry->cteList = transformWithClause(pstate, stmt->withClause);
2214  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
2215  }
2216 
2217  qry->resultRelation = setTargetTable(pstate, stmt->relation,
2218  stmt->relation->inh,
2219  true,
2220  ACL_UPDATE);
2221 
2222  /* grab the namespace item made by setTargetTable */
2223  nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
2224 
2225  /* subqueries in FROM cannot access the result relation */
2226  nsitem->p_lateral_only = true;
2227  nsitem->p_lateral_ok = false;
2228 
2229  /*
2230  * the FROM clause is non-standard SQL syntax. We used to be able to do
2231  * this with REPLACE in POSTQUEL so we keep the feature.
2232  */
2233  transformFromClause(pstate, stmt->fromClause);
2234 
2235  /* remaining clauses can reference the result relation normally */
2236  nsitem->p_lateral_only = false;
2237  nsitem->p_lateral_ok = true;
2238 
2239  qual = transformWhereClause(pstate, stmt->whereClause,
2240  EXPR_KIND_WHERE, "WHERE");
2241 
2242  qry->returningList = transformReturningList(pstate, stmt->returningList);
2243 
2244  /*
2245  * Now we are done with SELECT-like processing, and can get on with
2246  * transforming the target list to match the UPDATE target columns.
2247  */
2248  qry->targetList = transformUpdateTargetList(pstate, stmt->targetList);
2249 
2250  qry->rtable = pstate->p_rtable;
2251  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2252 
2253  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2254  qry->hasSubLinks = pstate->p_hasSubLinks;
2255 
2256  assign_query_collations(pstate, qry);
2257 
2258  return qry;
2259 }
List * fromClause
Definition: parsenodes.h:1503
bool p_hasSubLinks
Definition: parse_node.h:203
static List * transformUpdateTargetList(ParseState *pstate, List *targetList)
Definition: analyze.c:2266
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:284
FromExpr * jointree
Definition: parsenodes.h:138
int resultRelation
Definition: parsenodes.h:122
#define llast(l)
Definition: pg_list.h:131
bool p_hasTargetSRFs
Definition: parse_node.h:202
Definition: nodes.h:516
List * targetList
Definition: parsenodes.h:1501
static List * transformReturningList(ParseState *pstate, List *returningList)
Definition: analyze.c:2338
Node * whereClause
Definition: parsenodes.h:1502
List * targetList
Definition: parsenodes.h:140
bool hasRecursive
Definition: parsenodes.h:130
List * rtable
Definition: parsenodes.h:137
List * p_namespace
Definition: parse_node.h:178
bool recursive
Definition: parsenodes.h:1349
List * returningList
Definition: parsenodes.h:146
bool p_hasModifyingCTE
Definition: parse_node.h:204
bool inh
Definition: primnodes.h:69
#define ACL_UPDATE
Definition: parsenodes.h:76
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:112
bool hasTargetSRFs
Definition: parsenodes.h:127
#define makeNode(_type_)
Definition: nodes.h:564
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
RangeVar * relation
Definition: parsenodes.h:1500
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
List * returningList
Definition: parsenodes.h:1504
List * cteList
Definition: parsenodes.h:135
bool hasSubLinks
Definition: parsenodes.h:128
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:131
WithClause * withClause
Definition: parsenodes.h:1505
List * p_rtable
Definition: parse_node.h:174

◆ transformUpdateTargetList()

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

Definition at line 2266 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(), RelationGetNumberOfAttributes, RelationGetRelationName, TargetEntry::resjunk, TargetEntry::resname, TargetEntry::resno, transformTargetList(), RangeTblEntry::updatedCols, and updateTargetListEntry().

Referenced by transformOnConflictClause(), and transformUpdateStmt().

2267 {
2268  List *tlist = NIL;
2269  RangeTblEntry *target_rte;
2270  ListCell *orig_tl;
2271  ListCell *tl;
2272 
2273  tlist = transformTargetList(pstate, origTlist,
2275 
2276  /* Prepare to assign non-conflicting resnos to resjunk attributes */
2279 
2280  /* Prepare non-junk columns for assignment to target table */
2281  target_rte = pstate->p_target_rangetblentry;
2282  orig_tl = list_head(origTlist);
2283 
2284  foreach(tl, tlist)
2285  {
2286  TargetEntry *tle = (TargetEntry *) lfirst(tl);
2287  ResTarget *origTarget;
2288  int attrno;
2289 
2290  if (tle->resjunk)
2291  {
2292  /*
2293  * Resjunk nodes need no additional processing, but be sure they
2294  * have resnos that do not match any target columns; else rewriter
2295  * or planner might get confused. They don't need a resname
2296  * either.
2297  */
2298  tle->resno = (AttrNumber) pstate->p_next_resno++;
2299  tle->resname = NULL;
2300  continue;
2301  }
2302  if (orig_tl == NULL)
2303  elog(ERROR, "UPDATE target count mismatch --- internal error");
2304  origTarget = lfirst_node(ResTarget, orig_tl);
2305 
2306  attrno = attnameAttNum(pstate->p_target_relation,
2307  origTarget->name, true);
2308  if (attrno == InvalidAttrNumber)
2309  ereport(ERROR,
2310  (errcode(ERRCODE_UNDEFINED_COLUMN),
2311  errmsg("column \"%s\" of relation \"%s\" does not exist",
2312  origTarget->name,
2314  parser_errposition(pstate, origTarget->location)));
2315 
2316  updateTargetListEntry(pstate, tle, origTarget->name,
2317  attrno,
2318  origTarget->indirection,
2319  origTarget->location);
2320 
2321  /* Mark the target column as requiring update permissions */
2322  target_rte->updatedCols = bms_add_member(target_rte->updatedCols,
2324 
2325  orig_tl = lnext(orig_tl);
2326  }
2327  if (orig_tl != NULL)
2328  elog(ERROR, "UPDATE target count mismatch --- internal error");
2329 
2330  return tlist;
2331 }
List * indirection
Definition: parsenodes.h:442
#define NIL
Definition: pg_list.h:69
char * name
Definition: parsenodes.h:441
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:413
int errcode(int sqlerrcode)
Definition: elog.c:575
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
char * resname
Definition: primnodes.h:1377
int location
Definition: parsenodes.h:444
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:441
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:1074
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:764
#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 1317 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().

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

Variable Documentation

◆ post_parse_analyze_hook

post_parse_analyze_hook_type post_parse_analyze_hook = NULL