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_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 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 348 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().

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

◆ applyLockingClause()

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

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

2836 {
2837  RowMarkClause *rc;
2838 
2839  Assert(strength != LCS_NONE); /* else caller error */
2840 
2841  /* If it's an explicit clause, make sure hasForUpdate gets set */
2842  if (!pushedDown)
2843  qry->hasForUpdate = true;
2844 
2845  /* Check for pre-existing entry for same rtindex */
2846  if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
2847  {
2848  /*
2849  * If the same RTE is specified with more than one locking strength,
2850  * use the strongest. (Reasonable, since you can't take both a shared
2851  * and exclusive lock at the same time; it'll end up being exclusive
2852  * anyway.)
2853  *
2854  * Similarly, if the same RTE is specified with more than one lock
2855  * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
2856  * turn wins over waiting for the lock (the default). This is a bit
2857  * more debatable but raising an error doesn't seem helpful. (Consider
2858  * for instance SELECT FOR UPDATE NOWAIT from a view that internally
2859  * contains a plain FOR UPDATE spec.) Having NOWAIT win over SKIP
2860  * LOCKED is reasonable since the former throws an error in case of
2861  * coming across a locked tuple, which may be undesirable in some
2862  * cases but it seems better than silently returning inconsistent
2863  * results.
2864  *
2865  * And of course pushedDown becomes false if any clause is explicit.
2866  */
2867  rc->strength = Max(rc->strength, strength);
2868  rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
2869  rc->pushedDown &= pushedDown;
2870  return;
2871  }
2872 
2873  /* Make a new RowMarkClause */
2874  rc = makeNode(RowMarkClause);
2875  rc->rti = rtindex;
2876  rc->strength = strength;
2877  rc->waitPolicy = waitPolicy;
2878  rc->pushedDown = pushedDown;
2879  qry->rowMarks = lappend(qry->rowMarks, rc);
2880 }
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
List * rowMarks
Definition: parsenodes.h:161
LockClauseStrength strength
Definition: parsenodes.h:1314
List * lappend(List *list, void *datum)
Definition: list.c:128
#define Max(x, y)
Definition: c.h:796
#define makeNode(_type_)
Definition: nodes.h:560
#define Assert(condition)
Definition: c.h:670
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1315
bool hasForUpdate
Definition: parsenodes.h:130

◆ CheckSelectLocking()

void CheckSelectLocking ( Query qry,
LockClauseStrength  strength 
)

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

2599 {
2600  Assert(strength != LCS_NONE); /* else caller error */
2601 
2602  if (qry->setOperations)
2603  ereport(ERROR,
2604  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2605  /*------
2606  translator: %s is a SQL row locking clause such as FOR UPDATE */
2607  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
2608  LCS_asString(strength))));
2609  if (qry->distinctClause != NIL)
2610  ereport(ERROR,
2611  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2612  /*------
2613  translator: %s is a SQL row locking clause such as FOR UPDATE */
2614  errmsg("%s is not allowed with DISTINCT clause",
2615  LCS_asString(strength))));
2616  if (qry->groupClause != NIL)
2617  ereport(ERROR,
2618  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2619  /*------
2620  translator: %s is a SQL row locking clause such as FOR UPDATE */
2621  errmsg("%s is not allowed with GROUP BY clause",
2622  LCS_asString(strength))));
2623  if (qry->havingQual != NULL)
2624  ereport(ERROR,
2625  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2626  /*------
2627  translator: %s is a SQL row locking clause such as FOR UPDATE */
2628  errmsg("%s is not allowed with HAVING clause",
2629  LCS_asString(strength))));
2630  if (qry->hasAggs)
2631  ereport(ERROR,
2632  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2633  /*------
2634  translator: %s is a SQL row locking clause such as FOR UPDATE */
2635  errmsg("%s is not allowed with aggregate functions",
2636  LCS_asString(strength))));
2637  if (qry->hasWindowFuncs)
2638  ereport(ERROR,
2639  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2640  /*------
2641  translator: %s is a SQL row locking clause such as FOR UPDATE */
2642  errmsg("%s is not allowed with window functions",
2643  LCS_asString(strength))));
2644  if (qry->hasTargetSRFs)
2645  ereport(ERROR,
2646  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2647  /*------
2648  translator: %s is a SQL row locking clause such as FOR UPDATE */
2649  errmsg("%s is not allowed with set-returning functions in the target list",
2650  LCS_asString(strength))));
2651 }
#define NIL
Definition: pg_list.h:69
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2573
bool hasAggs
Definition: parsenodes.h:123
int errcode(int sqlerrcode)
Definition: elog.c:575
List * distinctClause
Definition: parsenodes.h:154
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool hasTargetSRFs
Definition: parsenodes.h:125
#define Assert(condition)
Definition: c.h:670
bool hasWindowFuncs
Definition: parsenodes.h:124
Node * setOperations
Definition: parsenodes.h:163
List * groupClause
Definition: parsenodes.h:146
int errmsg(const char *fmt,...)
Definition: elog.c:797
Node * havingQual
Definition: parsenodes.h:150

◆ count_rowexpr_columns()

static int count_rowexpr_columns ( ParseState pstate,
Node expr 
)
static

Definition at line 1130 of file analyze.c.

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

Referenced by transformInsertRow().

1131 {
1132  if (expr == NULL)
1133  return -1;
1134  if (IsA(expr, RowExpr))
1135  return list_length(((RowExpr *) expr)->args);
1136  if (IsA(expr, Var))
1137  {
1138  Var *var = (Var *) expr;
1139  AttrNumber attnum = var->varattno;
1140 
1141  if (attnum > 0 && var->vartype == RECORDOID)
1142  {
1143  RangeTblEntry *rte;
1144 
1145  rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup);
1146  if (rte->rtekind == RTE_SUBQUERY)
1147  {
1148  /* Subselect-in-FROM: examine sub-select's output expr */
1150  attnum);
1151 
1152  if (ste == NULL || ste->resjunk)
1153  return -1;
1154  expr = (Node *) ste->expr;
1155  if (IsA(expr, RowExpr))
1156  return list_length(((RowExpr *) expr)->args);
1157  }
1158  }
1159  }
1160  return -1;
1161 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
Index varlevelsup
Definition: primnodes.h:173
Definition: nodes.h:512
AttrNumber varattno
Definition: primnodes.h:168
Definition: primnodes.h:163
List * targetList
Definition: parsenodes.h:138
bool resjunk
Definition: primnodes.h:1382
Oid vartype
Definition: primnodes.h:170
#define RECORDOID
Definition: pg_type.h:680
Index varno
Definition: primnodes.h:166
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
Expr * expr
Definition: primnodes.h:1375
static int list_length(const List *l)
Definition: pg_list.h:89
RTEKind rtekind
Definition: parsenodes.h:951
Query * subquery
Definition: parsenodes.h:974
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 2135 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().

2136 {
2137  Node *node;
2138  int leftmostRTI;
2139  Query *leftmostQuery;
2140  List *targetList;
2141  ListCell *left_tlist;
2142  ListCell *nrtl;
2143  int next_resno;
2144 
2145  /*
2146  * Find leftmost leaf SELECT
2147  */
2148  node = larg;
2149  while (node && IsA(node, SetOperationStmt))
2150  node = ((SetOperationStmt *) node)->larg;
2151  Assert(node && IsA(node, RangeTblRef));
2152  leftmostRTI = ((RangeTblRef *) node)->rtindex;
2153  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2154  Assert(leftmostQuery != NULL);
2155 
2156  /*
2157  * Generate dummy targetlist using column names of leftmost select and
2158  * dummy result expressions of the non-recursive term.
2159  */
2160  targetList = NIL;
2161  left_tlist = list_head(leftmostQuery->targetList);
2162  next_resno = 1;
2163 
2164  foreach(nrtl, nrtargetlist)
2165  {
2166  TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
2167  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
2168  char *colName;
2169  TargetEntry *tle;
2170 
2171  Assert(!lefttle->resjunk);
2172  colName = pstrdup(lefttle->resname);
2173  tle = makeTargetEntry(nrtle->expr,
2174  next_resno++,
2175  colName,
2176  false);
2177  targetList = lappend(targetList, tle);
2178  left_tlist = lnext(left_tlist);
2179  }
2180 
2181  /* Now build CTE's output column info using dummy targetlist */
2182  analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
2183 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
void analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
Definition: parse_cte.c:352
char * pstrdup(const char *in)
Definition: mcxt.c:1076
Definition: nodes.h:512
char * resname
Definition: primnodes.h:1377
CommonTableExpr * p_parent_cte
Definition: parse_node.h:182
List * targetList
Definition: parsenodes.h:138
bool resjunk
Definition: primnodes.h:1382
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:237
List * lappend(List *list, void *datum)
Definition: list.c:128
#define Assert(condition)
Definition: c.h:670
#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:173

◆ LCS_asString()

const char* LCS_asString ( LockClauseStrength  strength)

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

2574 {
2575  switch (strength)
2576  {
2577  case LCS_NONE:
2578  Assert(false);
2579  break;
2580  case LCS_FORKEYSHARE:
2581  return "FOR KEY SHARE";
2582  case LCS_FORSHARE:
2583  return "FOR SHARE";
2584  case LCS_FORNOKEYUPDATE:
2585  return "FOR NO KEY UPDATE";
2586  case LCS_FORUPDATE:
2587  return "FOR UPDATE";
2588  }
2589  return "FOR some"; /* shouldn't happen */
2590 }
#define Assert(condition)
Definition: c.h:670

◆ parse_analyze()

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

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

99 {
100  ParseState *pstate = make_parsestate(NULL);
101  Query *query;
102 
103  Assert(sourceText != NULL); /* required as of 8.4 */
104 
105  pstate->p_sourcetext = sourceText;
106 
107  if (numParams > 0)
108  parse_fixed_parameters(pstate, paramTypes, numParams);
109 
110  pstate->p_queryEnv = queryEnv;
111 
112  query = transformTopLevelStmt(pstate, parseTree);
113 
115  (*post_parse_analyze_hook) (pstate, query);
116 
117  free_parsestate(pstate);
118 
119  return query;
120 }
QueryEnvironment * p_queryEnv
Definition: parse_node.h:196
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
const char * p_sourcetext
Definition: parse_node.h:172
#define Assert(condition)
Definition: c.h:670
void parse_fixed_parameters(ParseState *pstate, Oid *paramTypes, int numParams)
Definition: parse_param.c:67
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:187
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:49

◆ parse_analyze_varparams()

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

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

132 {
133  ParseState *pstate = make_parsestate(NULL);
134  Query *query;
135 
136  Assert(sourceText != NULL); /* required as of 8.4 */
137 
138  pstate->p_sourcetext = sourceText;
139 
140  parse_variable_parameters(pstate, paramTypes, numParams);
141 
142  query = transformTopLevelStmt(pstate, parseTree);
143 
144  /* make sure all is well with parameter types */
145  check_variable_parameters(pstate, query);
146 
148  (*post_parse_analyze_hook) (pstate, query);
149 
150  free_parsestate(pstate);
151 
152  return query;
153 }
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:172
#define Assert(condition)
Definition: c.h:670
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:187
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:49

◆ parse_sub_analyze()

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

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

164 {
165  ParseState *pstate = make_parsestate(parentParseState);
166  Query *query;
167 
168  pstate->p_parent_cte = parentCTE;
169  pstate->p_locked_from_parent = locked_from_parent;
170  pstate->p_resolve_unknowns = resolve_unknowns;
171 
172  query = transformStmt(pstate, parseTree);
173 
174  free_parsestate(pstate);
175 
176  return query;
177 }
CommonTableExpr * p_parent_cte
Definition: parse_node.h:182
bool p_locked_from_parent
Definition: parse_node.h:191
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
bool p_resolve_unknowns
Definition: parse_node.h:193
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:250
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77

◆ transformCreateTableAsStmt()

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

Definition at line 2496 of file analyze.c.

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

Referenced by transformStmt().

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

◆ transformDeclareCursorStmt()

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

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

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

◆ transformDeleteStmt()

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

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

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

◆ transformExplainStmt()

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

Definition at line 2472 of file analyze.c.

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

Referenced by transformStmt().

2473 {
2474  Query *result;
2475 
2476  /* transform contained query, allowing SELECT INTO */
2477  stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
2478 
2479  /* represent the command as a utility Query */
2480  result = makeNode(Query);
2481  result->commandType = CMD_UTILITY;
2482  result->utilityStmt = (Node *) stmt;
2483 
2484  return result;
2485 }
Definition: nodes.h:512
Node * utilityStmt
Definition: parsenodes.h:118
Node * query
Definition: parsenodes.h:3157
CmdType commandType
Definition: parsenodes.h:110
#define makeNode(_type_)
Definition: nodes.h:560
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:211

◆ transformInsertRow()

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

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

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

◆ transformInsertStmt()

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

Definition at line 458 of file analyze.c.

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

Referenced by transformStmt().

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

◆ transformLockingClause()

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

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

2664 {
2665  List *lockedRels = lc->lockedRels;
2666  ListCell *l;
2667  ListCell *rt;
2668  Index i;
2669  LockingClause *allrels;
2670 
2671  CheckSelectLocking(qry, lc->strength);
2672 
2673  /* make a clause we can pass down to subqueries to select all rels */
2674  allrels = makeNode(LockingClause);
2675  allrels->lockedRels = NIL; /* indicates all rels */
2676  allrels->strength = lc->strength;
2677  allrels->waitPolicy = lc->waitPolicy;
2678 
2679  if (lockedRels == NIL)
2680  {
2681  /* all regular tables used in query */
2682  i = 0;
2683  foreach(rt, qry->rtable)
2684  {
2685  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
2686 
2687  ++i;
2688  switch (rte->rtekind)
2689  {
2690  case RTE_RELATION:
2691  applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
2692  pushedDown);
2694  break;
2695  case RTE_SUBQUERY:
2696  applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
2697  pushedDown);
2698 
2699  /*
2700  * FOR UPDATE/SHARE of subquery is propagated to all of
2701  * subquery's rels, too. We could do this later (based on
2702  * the marking of the subquery RTE) but it is convenient
2703  * to have local knowledge in each query level about which
2704  * rels need to be opened with RowShareLock.
2705  */
2706  transformLockingClause(pstate, rte->subquery,
2707  allrels, true);
2708  break;
2709  default:
2710  /* ignore JOIN, SPECIAL, FUNCTION, VALUES, CTE RTEs */
2711  break;
2712  }
2713  }
2714  }
2715  else
2716  {
2717  /* just the named tables */
2718  foreach(l, lockedRels)
2719  {
2720  RangeVar *thisrel = (RangeVar *) lfirst(l);
2721 
2722  /* For simplicity we insist on unqualified alias names here */
2723  if (thisrel->catalogname || thisrel->schemaname)
2724  ereport(ERROR,
2725  (errcode(ERRCODE_SYNTAX_ERROR),
2726  /*------
2727  translator: %s is a SQL row locking clause such as FOR UPDATE */
2728  errmsg("%s must specify unqualified relation names",
2729  LCS_asString(lc->strength)),
2730  parser_errposition(pstate, thisrel->location)));
2731 
2732  i = 0;
2733  foreach(rt, qry->rtable)
2734  {
2735  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
2736 
2737  ++i;
2738  if (strcmp(rte->eref->aliasname, thisrel->relname) == 0)
2739  {
2740  switch (rte->rtekind)
2741  {
2742  case RTE_RELATION:
2743  applyLockingClause(qry, i, lc->strength,
2744  lc->waitPolicy, pushedDown);
2746  break;
2747  case RTE_SUBQUERY:
2748  applyLockingClause(qry, i, lc->strength,
2749  lc->waitPolicy, pushedDown);
2750  /* see comment above */
2751  transformLockingClause(pstate, rte->subquery,
2752  allrels, true);
2753  break;
2754  case RTE_JOIN:
2755  ereport(ERROR,
2756  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2757  /*------
2758  translator: %s is a SQL row locking clause such as FOR UPDATE */
2759  errmsg("%s cannot be applied to a join",
2760  LCS_asString(lc->strength)),
2761  parser_errposition(pstate, thisrel->location)));
2762  break;
2763  case RTE_FUNCTION:
2764  ereport(ERROR,
2765  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2766  /*------
2767  translator: %s is a SQL row locking clause such as FOR UPDATE */
2768  errmsg("%s cannot be applied to a function",
2769  LCS_asString(lc->strength)),
2770  parser_errposition(pstate, thisrel->location)));
2771  break;
2772  case RTE_TABLEFUNC:
2773  ereport(ERROR,
2774  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2775  /*------
2776  translator: %s is a SQL row locking clause such as FOR UPDATE */
2777  errmsg("%s cannot be applied to a table function",
2778  LCS_asString(lc->strength)),
2779  parser_errposition(pstate, thisrel->location)));
2780  break;
2781  case RTE_VALUES:
2782  ereport(ERROR,
2783  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2784  /*------
2785  translator: %s is a SQL row locking clause such as FOR UPDATE */
2786  errmsg("%s cannot be applied to VALUES",
2787  LCS_asString(lc->strength)),
2788  parser_errposition(pstate, thisrel->location)));
2789  break;
2790  case RTE_CTE:
2791  ereport(ERROR,
2792  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2793  /*------
2794  translator: %s is a SQL row locking clause such as FOR UPDATE */
2795  errmsg("%s cannot be applied to a WITH query",
2796  LCS_asString(lc->strength)),
2797  parser_errposition(pstate, thisrel->location)));
2798  break;
2799  case RTE_NAMEDTUPLESTORE:
2800  ereport(ERROR,
2801  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2802  /*------
2803  translator: %s is a SQL row locking clause such as FOR UPDATE */
2804  errmsg("%s cannot be applied to a named tuplestore",
2805  LCS_asString(lc->strength)),
2806  parser_errposition(pstate, thisrel->location)));
2807  break;
2808  default:
2809  elog(ERROR, "unrecognized RTE type: %d",
2810  (int) rte->rtekind);
2811  break;
2812  }
2813  break; /* out of foreach loop */
2814  }
2815  }
2816  if (rt == NULL)
2817  ereport(ERROR,
2819  /*------
2820  translator: %s is a SQL row locking clause such as FOR UPDATE */
2821  errmsg("relation \"%s\" in %s clause not found in FROM clause",
2822  thisrel->relname,
2823  LCS_asString(lc->strength)),
2824  parser_errposition(pstate, thisrel->location)));
2825  }
2826  }
2827 }
List * lockedRels
Definition: parsenodes.h:737
#define NIL
Definition: pg_list.h:69
static void transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc, bool pushedDown)
Definition: analyze.c:2662
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2573
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:61
int errcode(int sqlerrcode)
Definition: elog.c:575
AclMode requiredPerms
Definition: parsenodes.h:1059
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:2598
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
LockClauseStrength strength
Definition: parsenodes.h:738
#define ereport(elevel, rest)
Definition: elog.h:122
unsigned int Index
Definition: c.h:413
#define makeNode(_type_)
Definition: nodes.h:560
#define lfirst(lc)
Definition: pg_list.h:106
char * aliasname
Definition: primnodes.h:42
#define ACL_SELECT_FOR_UPDATE
Definition: parsenodes.h:88
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
RTEKind rtekind
Definition: parsenodes.h:951
Query * subquery
Definition: parsenodes.h:974
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define elog
Definition: elog.h:219
Alias * eref
Definition: parsenodes.h:1055
Definition: pg_list.h:45
LockWaitPolicy waitPolicy
Definition: parsenodes.h:739
char * catalogname
Definition: primnodes.h:66
void applyLockingClause(Query *qry, Index rtindex, LockClauseStrength strength, LockWaitPolicy waitPolicy, bool pushedDown)
Definition: analyze.c:2833

◆ transformOnConflictClause()

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

Definition at line 995 of file analyze.c.

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

Referenced by transformInsertStmt().

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

◆ transformOptionalSelectInto()

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

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

212 {
213  if (IsA(parseTree, SelectStmt))
214  {
215  SelectStmt *stmt = (SelectStmt *) parseTree;
216 
217  /* If it's a set-operation tree, drill down to leftmost SelectStmt */
218  while (stmt && stmt->op != SETOP_NONE)
219  stmt = stmt->larg;
220  Assert(stmt && IsA(stmt, SelectStmt) &&stmt->larg == NULL);
221 
222  if (stmt->intoClause)
223  {
225 
226  ctas->query = parseTree;
227  ctas->into = stmt->intoClause;
228  ctas->relkind = OBJECT_TABLE;
229  ctas->is_select_into = true;
230 
231  /*
232  * Remove the intoClause from the SelectStmt. This makes it safe
233  * for transformSelectStmt to complain if it finds intoClause set
234  * (implying that the INTO appeared in a disallowed place).
235  */
236  stmt->intoClause = NULL;
237 
238  parseTree = (Node *) ctas;
239  }
240  }
241 
242  return transformStmt(pstate, parseTree);
243 }
struct SelectStmt * larg
Definition: parsenodes.h:1552
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
IntoClause * intoClause
Definition: parsenodes.h:1519
Definition: nodes.h:512
ObjectType relkind
Definition: parsenodes.h:3179
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:250
SetOperation op
Definition: parsenodes.h:1550
IntoClause * into
Definition: parsenodes.h:3178
#define makeNode(_type_)
Definition: nodes.h:560
#define Assert(condition)
Definition: c.h:670

◆ transformReturningList()

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

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

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

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

◆ transformSetOperationStmt()

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

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

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

◆ transformSetOperationTree()

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

Definition at line 1787 of file analyze.c.

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

Referenced by transformSetOperationStmt().

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

◆ transformStmt()

Query* transformStmt ( ParseState pstate,
Node parseTree 
)

Definition at line 250 of file analyze.c.

References Query::canSetTag, CMD_UTILITY, Query::commandType, makeNode, nodeTag, SelectStmt::op, QSRC_ORIGINAL, Query::querySource, SETOP_NONE, T_CreateTableAsStmt, T_DeclareCursorStmt, T_DeleteStmt, T_ExplainStmt, T_InsertStmt, T_SelectStmt, T_UpdateStmt, 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().

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

◆ transformTopLevelStmt()

Query* transformTopLevelStmt ( ParseState pstate,
RawStmt parseTree 
)

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

188 {
189  Query *result;
190 
191  /* We're at top level, so allow SELECT INTO */
192  result = transformOptionalSelectInto(pstate, parseTree->stmt);
193 
194  result->stmt_location = parseTree->stmt_location;
195  result->stmt_len = parseTree->stmt_len;
196 
197  return result;
198 }
int stmt_location
Definition: parsenodes.h:179
Node * stmt
Definition: parsenodes.h:1431
int stmt_len
Definition: parsenodes.h:1433
int stmt_location
Definition: parsenodes.h:1432
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:211
int stmt_len
Definition: parsenodes.h:180

◆ transformUpdateStmt()

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

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

2192 {
2193  Query *qry = makeNode(Query);
2194  ParseNamespaceItem *nsitem;
2195  Node *qual;
2196 
2197  qry->commandType = CMD_UPDATE;
2198  pstate->p_is_insert = false;
2199 
2200  /* process the WITH clause independently of all else */
2201  if (stmt->withClause)
2202  {
2203  qry->hasRecursive = stmt->withClause->recursive;
2204  qry->cteList = transformWithClause(pstate, stmt->withClause);
2205  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
2206  }
2207 
2208  qry->resultRelation = setTargetTable(pstate, stmt->relation,
2209  stmt->relation->inh,
2210  true,
2211  ACL_UPDATE);
2212 
2213  /* grab the namespace item made by setTargetTable */
2214  nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
2215 
2216  /* subqueries in FROM cannot access the result relation */
2217  nsitem->p_lateral_only = true;
2218  nsitem->p_lateral_ok = false;
2219 
2220  /*
2221  * the FROM clause is non-standard SQL syntax. We used to be able to do
2222  * this with REPLACE in POSTQUEL so we keep the feature.
2223  */
2224  transformFromClause(pstate, stmt->fromClause);
2225 
2226  /* remaining clauses can reference the result relation normally */
2227  nsitem->p_lateral_only = false;
2228  nsitem->p_lateral_ok = true;
2229 
2230  qual = transformWhereClause(pstate, stmt->whereClause,
2231  EXPR_KIND_WHERE, "WHERE");
2232 
2233  qry->returningList = transformReturningList(pstate, stmt->returningList);
2234 
2235  /*
2236  * Now we are done with SELECT-like processing, and can get on with
2237  * transforming the target list to match the UPDATE target columns.
2238  */
2239  qry->targetList = transformUpdateTargetList(pstate, stmt->targetList);
2240 
2241  qry->rtable = pstate->p_rtable;
2242  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2243 
2244  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2245  qry->hasSubLinks = pstate->p_hasSubLinks;
2246 
2247  assign_query_collations(pstate, qry);
2248 
2249  return qry;
2250 }
List * fromClause
Definition: parsenodes.h:1484
bool p_hasSubLinks
Definition: parse_node.h:202
static List * transformUpdateTargetList(ParseState *pstate, List *targetList)
Definition: analyze.c:2257
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:284
FromExpr * jointree
Definition: parsenodes.h:136
int resultRelation
Definition: parsenodes.h:120
#define llast(l)
Definition: pg_list.h:131
bool p_hasTargetSRFs
Definition: parse_node.h:201
Definition: nodes.h:512
List * targetList
Definition: parsenodes.h:1482
static List * transformReturningList(ParseState *pstate, List *returningList)
Definition: analyze.c:2329
Node * whereClause
Definition: parsenodes.h:1483
List * targetList
Definition: parsenodes.h:138
bool hasRecursive
Definition: parsenodes.h:128
List * rtable
Definition: parsenodes.h:135
List * p_namespace
Definition: parse_node.h:177
bool recursive
Definition: parsenodes.h:1330
List * returningList
Definition: parsenodes.h:144
bool p_hasModifyingCTE
Definition: parse_node.h:203
bool inh
Definition: primnodes.h:69
#define ACL_UPDATE
Definition: parsenodes.h:74
void transformFromClause(ParseState *pstate, List *frmList)
Definition: parse_clause.c:112
int setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource, AclMode requiredPerms)
Definition: parse_clause.c:178
CmdType commandType
Definition: parsenodes.h:110
bool hasTargetSRFs
Definition: parsenodes.h:125
#define makeNode(_type_)
Definition: nodes.h:560
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
RangeVar * relation
Definition: parsenodes.h:1481
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
List * returningList
Definition: parsenodes.h:1485
List * cteList
Definition: parsenodes.h:133
bool hasSubLinks
Definition: parsenodes.h:126
void assign_query_collations(ParseState *pstate, Query *query)
bool p_is_insert
Definition: parse_node.h:185
List * p_joinlist
Definition: parse_node.h:175
bool hasModifyingCTE
Definition: parsenodes.h:129
WithClause * withClause
Definition: parsenodes.h:1486
List * p_rtable
Definition: parse_node.h:173

◆ transformUpdateTargetList()

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

Definition at line 2257 of file analyze.c.

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

Referenced by transformOnConflictClause(), and transformUpdateStmt().

2258 {
2259  List *tlist = NIL;
2260  RangeTblEntry *target_rte;
2261  ListCell *orig_tl;
2262  ListCell *tl;
2263 
2264  tlist = transformTargetList(pstate, origTlist,
2266 
2267  /* Prepare to assign non-conflicting resnos to resjunk attributes */
2268  if (pstate->p_next_resno <= pstate->p_target_relation->rd_rel->relnatts)
2269  pstate->p_next_resno = pstate->p_target_relation->rd_rel->relnatts + 1;
2270 
2271  /* Prepare non-junk columns for assignment to target table */
2272  target_rte = pstate->p_target_rangetblentry;
2273  orig_tl = list_head(origTlist);
2274 
2275  foreach(tl, tlist)
2276  {
2277  TargetEntry *tle = (TargetEntry *) lfirst(tl);
2278  ResTarget *origTarget;
2279  int attrno;
2280 
2281  if (tle->resjunk)
2282  {
2283  /*
2284  * Resjunk nodes need no additional processing, but be sure they
2285  * have resnos that do not match any target columns; else rewriter
2286  * or planner might get confused. They don't need a resname
2287  * either.
2288  */
2289  tle->resno = (AttrNumber) pstate->p_next_resno++;
2290  tle->resname = NULL;
2291  continue;
2292  }
2293  if (orig_tl == NULL)
2294  elog(ERROR, "UPDATE target count mismatch --- internal error");
2295  origTarget = lfirst_node(ResTarget, orig_tl);
2296 
2297  attrno = attnameAttNum(pstate->p_target_relation,
2298  origTarget->name, true);
2299  if (attrno == InvalidAttrNumber)
2300  ereport(ERROR,
2301  (errcode(ERRCODE_UNDEFINED_COLUMN),
2302  errmsg("column \"%s\" of relation \"%s\" does not exist",
2303  origTarget->name,
2305  parser_errposition(pstate, origTarget->location)));
2306 
2307  updateTargetListEntry(pstate, tle, origTarget->name,
2308  attrno,
2309  origTarget->indirection,
2310  origTarget->location);
2311 
2312  /* Mark the target column as requiring update permissions */
2313  target_rte->updatedCols = bms_add_member(target_rte->updatedCols,
2315 
2316  orig_tl = lnext(orig_tl);
2317  }
2318  if (orig_tl != NULL)
2319  elog(ERROR, "UPDATE target count mismatch --- internal error");
2320 
2321  return tlist;
2322 }
List * indirection
Definition: parsenodes.h:440
#define NIL
Definition: pg_list.h:69
char * name
Definition: parsenodes.h:439
int errcode(int sqlerrcode)
Definition: elog.c:575
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
Form_pg_class rd_rel
Definition: rel.h:114
char * resname
Definition: primnodes.h:1377
int location
Definition: parsenodes.h:442
List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind)
Definition: parse_target.c:131
bool resjunk
Definition: primnodes.h:1382
#define ERROR
Definition: elog.h:43
#define lfirst_node(type, lc)
Definition: pg_list.h:109
AttrNumber resno
Definition: primnodes.h:1376
int p_next_resno
Definition: parse_node.h:188
#define RelationGetRelationName(relation)
Definition: rel.h:445
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
RangeTblEntry * p_target_rangetblentry
Definition: parse_node.h:184
Bitmapset * updatedCols
Definition: parsenodes.h:1063
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:698
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:797
Relation p_target_relation
Definition: parse_node.h:183
#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 1308 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().

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

Variable Documentation

◆ post_parse_analyze_hook

post_parse_analyze_hook_type post_parse_analyze_hook = NULL