PostgreSQL Source Code  git master
analyze.c File Reference
Include dependency graph for analyze.c:

Go to the source code of this file.

Functions

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

Variables

post_parse_analyze_hook_type post_parse_analyze_hook = NULL
 

Function Documentation

◆ analyze_requires_snapshot()

bool analyze_requires_snapshot ( RawStmt parseTree)

Definition at line 357 of file analyze.c.

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

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

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

◆ applyLockingClause()

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

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

2947 {
2948  RowMarkClause *rc;
2949 
2950  Assert(strength != LCS_NONE); /* else caller error */
2951 
2952  /* If it's an explicit clause, make sure hasForUpdate gets set */
2953  if (!pushedDown)
2954  qry->hasForUpdate = true;
2955 
2956  /* Check for pre-existing entry for same rtindex */
2957  if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
2958  {
2959  /*
2960  * If the same RTE is specified with more than one locking strength,
2961  * use the strongest. (Reasonable, since you can't take both a shared
2962  * and exclusive lock at the same time; it'll end up being exclusive
2963  * anyway.)
2964  *
2965  * Similarly, if the same RTE is specified with more than one lock
2966  * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
2967  * turn wins over waiting for the lock (the default). This is a bit
2968  * more debatable but raising an error doesn't seem helpful. (Consider
2969  * for instance SELECT FOR UPDATE NOWAIT from a view that internally
2970  * contains a plain FOR UPDATE spec.) Having NOWAIT win over SKIP
2971  * LOCKED is reasonable since the former throws an error in case of
2972  * coming across a locked tuple, which may be undesirable in some
2973  * cases but it seems better than silently returning inconsistent
2974  * results.
2975  *
2976  * And of course pushedDown becomes false if any clause is explicit.
2977  */
2978  rc->strength = Max(rc->strength, strength);
2979  rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
2980  rc->pushedDown &= pushedDown;
2981  return;
2982  }
2983 
2984  /* Make a new RowMarkClause */
2985  rc = makeNode(RowMarkClause);
2986  rc->rti = rtindex;
2987  rc->strength = strength;
2988  rc->waitPolicy = waitPolicy;
2989  rc->pushedDown = pushedDown;
2990  qry->rowMarks = lappend(qry->rowMarks, rc);
2991 }
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
List * rowMarks
Definition: parsenodes.h:164
LockClauseStrength strength
Definition: parsenodes.h:1384
List * lappend(List *list, void *datum)
Definition: list.c:321
#define Max(x, y)
Definition: c.h:922
#define makeNode(_type_)
Definition: nodes.h:576
#define Assert(condition)
Definition: c.h:746
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1385
bool hasForUpdate
Definition: parsenodes.h:132

◆ BuildOnConflictExcludedTargetlist()

List* BuildOnConflictExcludedTargetlist ( Relation  targetrel,
Index  exclRelIndex 
)

Definition at line 1078 of file analyze.c.

References InvalidAttrNumber, InvalidOid, lappend(), makeNullConst(), makeTargetEntry(), makeVar(), name, NameStr, NIL, pstrdup(), RelationData::rd_att, RelationData::rd_rel, RelationGetNumberOfAttributes, and TupleDescAttr.

Referenced by rewriteTargetView(), and transformOnConflictClause().

1080 {
1081  List *result = NIL;
1082  int attno;
1083  Var *var;
1084  TargetEntry *te;
1085 
1086  /*
1087  * Note that resnos of the tlist must correspond to attnos of the
1088  * underlying relation, hence we need entries for dropped columns too.
1089  */
1090  for (attno = 0; attno < RelationGetNumberOfAttributes(targetrel); attno++)
1091  {
1092  Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno);
1093  char *name;
1094 
1095  if (attr->attisdropped)
1096  {
1097  /*
1098  * can't use atttypid here, but it doesn't really matter what type
1099  * the Const claims to be.
1100  */
1101  var = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
1102  name = NULL;
1103  }
1104  else
1105  {
1106  var = makeVar(exclRelIndex, attno + 1,
1107  attr->atttypid, attr->atttypmod,
1108  attr->attcollation,
1109  0);
1110  name = pstrdup(NameStr(attr->attname));
1111  }
1112 
1113  te = makeTargetEntry((Expr *) var,
1114  attno + 1,
1115  name,
1116  false);
1117 
1118  result = lappend(result, te);
1119  }
1120 
1121  /*
1122  * Add a whole-row-Var entry to support references to "EXCLUDED.*". Like
1123  * the other entries in the EXCLUDED tlist, its resno must match the Var's
1124  * varattno, else the wrong things happen while resolving references in
1125  * setrefs.c. This is against normal conventions for targetlists, but
1126  * it's okay since we don't use this as a real tlist.
1127  */
1128  var = makeVar(exclRelIndex, InvalidAttrNumber,
1129  targetrel->rd_rel->reltype,
1130  -1, InvalidOid, 0);
1131  te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
1132  result = lappend(result, te);
1133 
1134  return result;
1135 }
#define NIL
Definition: pg_list.h:65
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:462
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
char * pstrdup(const char *in)
Definition: mcxt.c:1187
Form_pg_class rd_rel
Definition: rel.h:109
Definition: primnodes.h:181
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:337
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
List * lappend(List *list, void *datum)
Definition: list.c:321
TupleDesc rd_att
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
const char * name
Definition: encode.c:561
#define InvalidAttrNumber
Definition: attnum.h:23
#define NameStr(name)
Definition: c.h:623
Definition: pg_list.h:50

◆ CheckSelectLocking()

void CheckSelectLocking ( Query qry,
LockClauseStrength  strength 
)

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

2707 {
2708  Assert(strength != LCS_NONE); /* else caller error */
2709 
2710  if (qry->setOperations)
2711  ereport(ERROR,
2712  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2713  /*------
2714  translator: %s is a SQL row locking clause such as FOR UPDATE */
2715  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
2716  LCS_asString(strength))));
2717  if (qry->distinctClause != NIL)
2718  ereport(ERROR,
2719  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2720  /*------
2721  translator: %s is a SQL row locking clause such as FOR UPDATE */
2722  errmsg("%s is not allowed with DISTINCT clause",
2723  LCS_asString(strength))));
2724  if (qry->groupClause != NIL)
2725  ereport(ERROR,
2726  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2727  /*------
2728  translator: %s is a SQL row locking clause such as FOR UPDATE */
2729  errmsg("%s is not allowed with GROUP BY clause",
2730  LCS_asString(strength))));
2731  if (qry->havingQual != NULL)
2732  ereport(ERROR,
2733  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2734  /*------
2735  translator: %s is a SQL row locking clause such as FOR UPDATE */
2736  errmsg("%s is not allowed with HAVING clause",
2737  LCS_asString(strength))));
2738  if (qry->hasAggs)
2739  ereport(ERROR,
2740  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2741  /*------
2742  translator: %s is a SQL row locking clause such as FOR UPDATE */
2743  errmsg("%s is not allowed with aggregate functions",
2744  LCS_asString(strength))));
2745  if (qry->hasWindowFuncs)
2746  ereport(ERROR,
2747  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2748  /*------
2749  translator: %s is a SQL row locking clause such as FOR UPDATE */
2750  errmsg("%s is not allowed with window functions",
2751  LCS_asString(strength))));
2752  if (qry->hasTargetSRFs)
2753  ereport(ERROR,
2754  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2755  /*------
2756  translator: %s is a SQL row locking clause such as FOR UPDATE */
2757  errmsg("%s is not allowed with set-returning functions in the target list",
2758  LCS_asString(strength))));
2759 }
#define NIL
Definition: pg_list.h:65
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2681
bool hasAggs
Definition: parsenodes.h:125
int errcode(int sqlerrcode)
Definition: elog.c:610
List * distinctClause
Definition: parsenodes.h:156
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
bool hasTargetSRFs
Definition: parsenodes.h:127
#define Assert(condition)
Definition: c.h:746
bool hasWindowFuncs
Definition: parsenodes.h:126
Node * setOperations
Definition: parsenodes.h:166
List * groupClause
Definition: parsenodes.h:148
int errmsg(const char *fmt,...)
Definition: elog.c:821
Node * havingQual
Definition: parsenodes.h:152

◆ count_rowexpr_columns()

static int count_rowexpr_columns ( ParseState pstate,
Node expr 
)
static

Definition at line 1148 of file analyze.c.

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

Referenced by transformInsertRow().

1149 {
1150  if (expr == NULL)
1151  return -1;
1152  if (IsA(expr, RowExpr))
1153  return list_length(((RowExpr *) expr)->args);
1154  if (IsA(expr, Var))
1155  {
1156  Var *var = (Var *) expr;
1157  AttrNumber attnum = var->varattno;
1158 
1159  if (attnum > 0 && var->vartype == RECORDOID)
1160  {
1161  RangeTblEntry *rte;
1162 
1163  rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup);
1164  if (rte->rtekind == RTE_SUBQUERY)
1165  {
1166  /* Subselect-in-FROM: examine sub-select's output expr */
1168  attnum);
1169 
1170  if (ste == NULL || ste->resjunk)
1171  return -1;
1172  expr = (Node *) ste->expr;
1173  if (IsA(expr, RowExpr))
1174  return list_length(((RowExpr *) expr)->args);
1175  }
1176  }
1177  }
1178  return -1;
1179 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
Index varlevelsup
Definition: primnodes.h:191
Definition: nodes.h:528
AttrNumber varattno
Definition: primnodes.h:186
Definition: primnodes.h:181
List * targetList
Definition: parsenodes.h:140
bool resjunk
Definition: primnodes.h:1417
Oid vartype
Definition: primnodes.h:188
Index varno
Definition: primnodes.h:184
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
int16 attnum
Definition: pg_attribute.h:79
Expr * expr
Definition: primnodes.h:1410
static int list_length(const List *l)
Definition: pg_list.h:149
RTEKind rtekind
Definition: parsenodes.h:977
Query * subquery
Definition: parsenodes.h:1012
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 2175 of file analyze.c.

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

Referenced by transformSetOperationTree().

2176 {
2177  Node *node;
2178  int leftmostRTI;
2179  Query *leftmostQuery;
2180  List *targetList;
2181  ListCell *left_tlist;
2182  ListCell *nrtl;
2183  int next_resno;
2184 
2185  /*
2186  * Find leftmost leaf SELECT
2187  */
2188  node = larg;
2189  while (node && IsA(node, SetOperationStmt))
2190  node = ((SetOperationStmt *) node)->larg;
2191  Assert(node && IsA(node, RangeTblRef));
2192  leftmostRTI = ((RangeTblRef *) node)->rtindex;
2193  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2194  Assert(leftmostQuery != NULL);
2195 
2196  /*
2197  * Generate dummy targetlist using column names of leftmost select and
2198  * dummy result expressions of the non-recursive term.
2199  */
2200  targetList = NIL;
2201  next_resno = 1;
2202 
2203  forboth(nrtl, nrtargetlist, left_tlist, leftmostQuery->targetList)
2204  {
2205  TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
2206  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
2207  char *colName;
2208  TargetEntry *tle;
2209 
2210  Assert(!lefttle->resjunk);
2211  colName = pstrdup(lefttle->resname);
2212  tle = makeTargetEntry(nrtle->expr,
2213  next_resno++,
2214  colName,
2215  false);
2216  targetList = lappend(targetList, tle);
2217  }
2218 
2219  /* Now build CTE's output column info using dummy targetlist */
2220  analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
2221 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:434
void analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
Definition: parse_cte.c:352
char * pstrdup(const char *in)
Definition: mcxt.c:1187
Definition: nodes.h:528
char * resname
Definition: primnodes.h:1412
CommonTableExpr * p_parent_cte
Definition: parse_node.h:189
List * targetList
Definition: parsenodes.h:140
bool resjunk
Definition: primnodes.h:1417
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
List * lappend(List *list, void *datum)
Definition: list.c:321
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1410
Definition: pg_list.h:50
List * p_rtable
Definition: parse_node.h:180

◆ fill_extraUpdatedCols()

void fill_extraUpdatedCols ( RangeTblEntry target_rte,
TupleDesc  tupdesc 
)

Definition at line 2368 of file analyze.c.

References AttrDefault::adbin, AttrDefault::adnum, bms_add_member(), bms_overlap(), TupleDescData::constr, TupleConstr::defval, RangeTblEntry::extraUpdatedCols, FirstLowInvalidHeapAttributeNumber, TupleConstr::has_generated_stored, i, TupleConstr::num_defval, pull_varattnos(), stringToNode(), TupleDescAttr, and RangeTblEntry::updatedCols.

Referenced by apply_handle_update(), and transformUpdateTargetList().

2369 {
2370  if (tupdesc->constr &&
2371  tupdesc->constr->has_generated_stored)
2372  {
2373  for (int i = 0; i < tupdesc->constr->num_defval; i++)
2374  {
2375  AttrDefault defval = tupdesc->constr->defval[i];
2376  Node *expr;
2377  Bitmapset *attrs_used = NULL;
2378 
2379  /* skip if not generated column */
2380  if (!TupleDescAttr(tupdesc, defval.adnum - 1)->attgenerated)
2381  continue;
2382 
2383  expr = stringToNode(defval.adbin);
2384  pull_varattnos(expr, 1, &attrs_used);
2385 
2386  if (bms_overlap(target_rte->updatedCols, attrs_used))
2387  target_rte->extraUpdatedCols = bms_add_member(target_rte->extraUpdatedCols,
2389  }
2390  }
2391 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Definition: nodes.h:528
void * stringToNode(const char *str)
Definition: read.c:89
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:219
AttrDefault * defval
Definition: tupdesc.h:39
bool has_generated_stored
Definition: tupdesc.h:45
Bitmapset * extraUpdatedCols
Definition: parsenodes.h:1125
TupleConstr * constr
Definition: tupdesc.h:85
Bitmapset * updatedCols
Definition: parsenodes.h:1124
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:494
uint16 num_defval
Definition: tupdesc.h:42
int i
AttrNumber adnum
Definition: tupdesc.h:24
char * adbin
Definition: tupdesc.h:25

◆ LCS_asString()

const char* LCS_asString ( LockClauseStrength  strength)

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

2682 {
2683  switch (strength)
2684  {
2685  case LCS_NONE:
2686  Assert(false);
2687  break;
2688  case LCS_FORKEYSHARE:
2689  return "FOR KEY SHARE";
2690  case LCS_FORSHARE:
2691  return "FOR SHARE";
2692  case LCS_FORNOKEYUPDATE:
2693  return "FOR NO KEY UPDATE";
2694  case LCS_FORUPDATE:
2695  return "FOR UPDATE";
2696  }
2697  return "FOR some"; /* shouldn't happen */
2698 }
#define Assert(condition)
Definition: c.h:746

◆ parse_analyze()

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

Definition at line 100 of file analyze.c.

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

Referenced by DefineView(), and pg_analyze_and_rewrite().

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

◆ parse_analyze_varparams()

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

Definition at line 134 of file analyze.c.

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

Referenced by exec_parse_message(), and PrepareQuery().

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

◆ parse_sub_analyze()

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

Definition at line 164 of file analyze.c.

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

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

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

◆ transformCallStmt()

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

Definition at line 2642 of file analyze.c.

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

Referenced by transformStmt().

2643 {
2644  List *targs;
2645  ListCell *lc;
2646  Node *node;
2647  Query *result;
2648 
2649  targs = NIL;
2650  foreach(lc, stmt->funccall->args)
2651  {
2652  targs = lappend(targs, transformExpr(pstate,
2653  (Node *) lfirst(lc),
2655  }
2656 
2657  node = ParseFuncOrColumn(pstate,
2658  stmt->funccall->funcname,
2659  targs,
2660  pstate->p_last_srf,
2661  stmt->funccall,
2662  true,
2663  stmt->funccall->location);
2664 
2665  assign_expr_collations(pstate, node);
2666 
2667  stmt->funcexpr = castNode(FuncExpr, node);
2668 
2669  result = makeNode(Query);
2670  result->commandType = CMD_UTILITY;
2671  result->utilityStmt = (Node *) stmt;
2672 
2673  return result;
2674 }
#define NIL
Definition: pg_list.h:65
FuncExpr * funcexpr
Definition: parsenodes.h:2903
#define castNode(_type_, nodeptr)
Definition: nodes.h:597
FuncCall * funccall
Definition: parsenodes.h:2902
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:145
Definition: nodes.h:528
int location
Definition: parsenodes.h:361
Node * utilityStmt
Definition: parsenodes.h:120
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *last_srf, FuncCall *fn, bool proc_call, int location)
Definition: parse_func.c:88
List * lappend(List *list, void *datum)
Definition: list.c:321
Node * p_last_srf
Definition: parse_node.h:212
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:576
#define lfirst(lc)
Definition: pg_list.h:169
List * args
Definition: parsenodes.h:353
List * funcname
Definition: parsenodes.h:352
Definition: pg_list.h:50

◆ transformCreateTableAsStmt()

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

Definition at line 2565 of file analyze.c.

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

Referenced by transformStmt().

2566 {
2567  Query *result;
2568  Query *query;
2569 
2570  /* transform contained query, not allowing SELECT INTO */
2571  query = transformStmt(pstate, stmt->query);
2572  stmt->query = (Node *) query;
2573 
2574  /* additional work needed for CREATE MATERIALIZED VIEW */
2575  if (stmt->objtype == OBJECT_MATVIEW)
2576  {
2577  /*
2578  * Prohibit a data-modifying CTE in the query used to create a
2579  * materialized view. It's not sufficiently clear what the user would
2580  * want to happen if the MV is refreshed or incrementally maintained.
2581  */
2582  if (query->hasModifyingCTE)
2583  ereport(ERROR,
2584  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2585  errmsg("materialized views must not use data-modifying statements in WITH")));
2586 
2587  /*
2588  * Check whether any temporary database objects are used in the
2589  * creation query. It would be hard to refresh data or incrementally
2590  * maintain it if a source disappeared.
2591  */
2592  if (isQueryUsingTempRelation(query))
2593  ereport(ERROR,
2594  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2595  errmsg("materialized views must not use temporary tables or views")));
2596 
2597  /*
2598  * A materialized view would either need to save parameters for use in
2599  * maintaining/loading the data or prohibit them entirely. The latter
2600  * seems safer and more sane.
2601  */
2602  if (query_contains_extern_params(query))
2603  ereport(ERROR,
2604  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2605  errmsg("materialized views may not be defined using bound parameters")));
2606 
2607  /*
2608  * For now, we disallow unlogged materialized views, because it seems
2609  * like a bad idea for them to just go to empty after a crash. (If we
2610  * could mark them as unpopulated, that would be better, but that
2611  * requires catalog changes which crash recovery can't presently
2612  * handle.)
2613  */
2614  if (stmt->into->rel->relpersistence == RELPERSISTENCE_UNLOGGED)
2615  ereport(ERROR,
2616  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2617  errmsg("materialized views cannot be unlogged")));
2618 
2619  /*
2620  * At runtime, we'll need a copy of the parsed-but-not-rewritten Query
2621  * for purposes of creating the view's ON SELECT rule. We stash that
2622  * in the IntoClause because that's where intorel_startup() can
2623  * conveniently get it from.
2624  */
2625  stmt->into->viewQuery = (Node *) copyObject(query);
2626  }
2627 
2628  /* represent the command as a utility Query */
2629  result = makeNode(Query);
2630  result->commandType = CMD_UTILITY;
2631  result->utilityStmt = (Node *) stmt;
2632 
2633  return result;
2634 }
bool isQueryUsingTempRelation(Query *query)
Definition: nodes.h:528
int errcode(int sqlerrcode)
Definition: elog.c:610
Node * utilityStmt
Definition: parsenodes.h:120
ObjectType objtype
Definition: parsenodes.h:3280
#define ERROR
Definition: elog.h:43
Node * viewQuery
Definition: primnodes.h:118
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:254
#define ereport(elevel,...)
Definition: elog.h:144
IntoClause * into
Definition: parsenodes.h:3279
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:576
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:821
RangeVar * rel
Definition: primnodes.h:112
bool hasModifyingCTE
Definition: parsenodes.h:131
#define copyObject(obj)
Definition: nodes.h:644

◆ transformDeclareCursorStmt()

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

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

2456 {
2457  Query *result;
2458  Query *query;
2459 
2460  /*
2461  * Don't allow both SCROLL and NO SCROLL to be specified
2462  */
2463  if ((stmt->options & CURSOR_OPT_SCROLL) &&
2464  (stmt->options & CURSOR_OPT_NO_SCROLL))
2465  ereport(ERROR,
2466  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2467  errmsg("cannot specify both SCROLL and NO SCROLL")));
2468 
2469  /* Transform contained query, not allowing SELECT INTO */
2470  query = transformStmt(pstate, stmt->query);
2471  stmt->query = (Node *) query;
2472 
2473  /* Grammar should not have allowed anything but SELECT */
2474  if (!IsA(query, Query) ||
2475  query->commandType != CMD_SELECT)
2476  elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR");
2477 
2478  /*
2479  * We also disallow data-modifying WITH in a cursor. (This could be
2480  * allowed, but the semantics of when the updates occur might be
2481  * surprising.)
2482  */
2483  if (query->hasModifyingCTE)
2484  ereport(ERROR,
2485  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2486  errmsg("DECLARE CURSOR must not contain data-modifying statements in WITH")));
2487 
2488  /* FOR UPDATE and WITH HOLD are not compatible */
2489  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
2490  ereport(ERROR,
2491  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2492  /*------
2493  translator: %s is a SQL row locking clause such as FOR UPDATE */
2494  errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
2496  linitial(query->rowMarks))->strength)),
2497  errdetail("Holdable cursors must be READ ONLY.")));
2498 
2499  /* FOR UPDATE and SCROLL are not compatible */
2500  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
2501  ereport(ERROR,
2502  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2503  /*------
2504  translator: %s is a SQL row locking clause such as FOR UPDATE */
2505  errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
2507  linitial(query->rowMarks))->strength)),
2508  errdetail("Scrollable cursors must be READ ONLY.")));
2509 
2510  /* FOR UPDATE and INSENSITIVE are not compatible */
2511  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
2512  ereport(ERROR,
2513  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2514  /*------
2515  translator: %s is a SQL row locking clause such as FOR UPDATE */
2516  errmsg("DECLARE INSENSITIVE CURSOR ... %s is not supported",
2518  linitial(query->rowMarks))->strength)),
2519  errdetail("Insensitive cursors must be READ ONLY.")));
2520 
2521  /* represent the command as a utility Query */
2522  result = makeNode(Query);
2523  result->commandType = CMD_UTILITY;
2524  result->utilityStmt = (Node *) stmt;
2525 
2526  return result;
2527 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2681
#define CURSOR_OPT_HOLD
Definition: parsenodes.h:2712
Definition: nodes.h:528
int errcode(int sqlerrcode)
Definition: elog.c:610
#define CURSOR_OPT_INSENSITIVE
Definition: parsenodes.h:2711
List * rowMarks
Definition: parsenodes.h:164
Node * utilityStmt
Definition: parsenodes.h:120
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:2710
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:954
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:254
#define ereport(elevel,...)
Definition: elog.h:144
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:576
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define elog(elevel,...)
Definition: elog.h:214
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2709
bool hasModifyingCTE
Definition: parsenodes.h:131

◆ transformDeleteStmt()

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

Definition at line 397 of file analyze.c.

References ACL_DELETE, assign_query_collations(), CMD_DELETE, Query::commandType, Query::cteList, Query::distinctClause, EXPR_KIND_WHERE, Query::hasAggs, Query::hasModifyingCTE, Query::hasRecursive, Query::hasSubLinks, Query::hasTargetSRFs, Query::hasWindowFuncs, RangeVar::inh, Query::jointree, 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_rtable, ParseState::p_target_nsitem, parseCheckAggregates(), WithClause::recursive, DeleteStmt::relation, Query::resultRelation, Query::returningList, DeleteStmt::returningList, Query::rtable, setTargetTable(), transformFromClause(), transformReturningList(), transformWhereClause(), transformWithClause(), DeleteStmt::usingClause, DeleteStmt::whereClause, and DeleteStmt::withClause.

Referenced by transformStmt().

398 {
399  Query *qry = makeNode(Query);
400  ParseNamespaceItem *nsitem;
401  Node *qual;
402 
403  qry->commandType = CMD_DELETE;
404 
405  /* process the WITH clause independently of all else */
406  if (stmt->withClause)
407  {
408  qry->hasRecursive = stmt->withClause->recursive;
409  qry->cteList = transformWithClause(pstate, stmt->withClause);
410  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
411  }
412 
413  /* set up range table with just the result rel */
414  qry->resultRelation = setTargetTable(pstate, stmt->relation,
415  stmt->relation->inh,
416  true,
417  ACL_DELETE);
418  nsitem = pstate->p_target_nsitem;
419 
420  /* there's no DISTINCT in DELETE */
421  qry->distinctClause = NIL;
422 
423  /* subqueries in USING cannot access the result relation */
424  nsitem->p_lateral_only = true;
425  nsitem->p_lateral_ok = false;
426 
427  /*
428  * The USING clause is non-standard SQL syntax, and is equivalent in
429  * functionality to the FROM list that can be specified for UPDATE. The
430  * USING keyword is used rather than FROM because FROM is already a
431  * keyword in the DELETE syntax.
432  */
433  transformFromClause(pstate, stmt->usingClause);
434 
435  /* remaining clauses can reference the result relation normally */
436  nsitem->p_lateral_only = false;
437  nsitem->p_lateral_ok = true;
438 
439  qual = transformWhereClause(pstate, stmt->whereClause,
440  EXPR_KIND_WHERE, "WHERE");
441 
442  qry->returningList = transformReturningList(pstate, stmt->returningList);
443 
444  /* done building the range table and jointree */
445  qry->rtable = pstate->p_rtable;
446  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
447 
448  qry->hasSubLinks = pstate->p_hasSubLinks;
449  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
450  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
451  qry->hasAggs = pstate->p_hasAggs;
452 
453  assign_query_collations(pstate, qry);
454 
455  /* this must be done after collations, for reliable comparison of exprs */
456  if (pstate->p_hasAggs)
457  parseCheckAggregates(pstate, qry);
458 
459  return qry;
460 }
#define NIL
Definition: pg_list.h:65
bool p_hasSubLinks
Definition: parse_node.h:209
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:285
RangeVar * relation
Definition: parsenodes.h:1545
FromExpr * jointree
Definition: parsenodes.h:138
bool hasAggs
Definition: parsenodes.h:125
int resultRelation
Definition: parsenodes.h:122
bool p_hasTargetSRFs
Definition: parse_node.h:208
Definition: nodes.h:528
#define ACL_DELETE
Definition: parsenodes.h:77
bool p_hasAggs
Definition: parse_node.h:206
static List * transformReturningList(ParseState *pstate, List *returningList)
Definition: analyze.c:2398
ParseNamespaceItem * p_target_nsitem
Definition: parse_node.h:191
void parseCheckAggregates(ParseState *pstate, Query *qry)
Definition: parse_agg.c:1042
bool p_hasWindowFuncs
Definition: parse_node.h:207
bool hasRecursive
Definition: parsenodes.h:130
WithClause * withClause
Definition: parsenodes.h:1549
List * returningList
Definition: parsenodes.h:1548
List * rtable
Definition: parsenodes.h:137
List * distinctClause
Definition: parsenodes.h:156
bool recursive
Definition: parsenodes.h:1400
List * returningList
Definition: parsenodes.h:146
bool p_hasModifyingCTE
Definition: parse_node.h:210
bool inh
Definition: primnodes.h:69
void transformFromClause(ParseState *pstate, List *frmList)
Definition: parse_clause.c:114
Node * whereClause
Definition: parsenodes.h:1547
List * usingClause
Definition: parsenodes.h:1546
int setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource, AclMode requiredPerms)
Definition: parse_clause.c:178
CmdType commandType
Definition: parsenodes.h:112
bool hasTargetSRFs
Definition: parsenodes.h:127
#define makeNode(_type_)
Definition: nodes.h:576
bool hasWindowFuncs
Definition: parsenodes.h:126
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
List * cteList
Definition: parsenodes.h:135
bool hasSubLinks
Definition: parsenodes.h:128
void assign_query_collations(ParseState *pstate, Query *query)
List * p_joinlist
Definition: parse_node.h:182
bool hasModifyingCTE
Definition: parsenodes.h:131
List * p_rtable
Definition: parse_node.h:180

◆ transformExplainStmt()

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

Definition at line 2541 of file analyze.c.

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

Referenced by transformStmt().

2542 {
2543  Query *result;
2544 
2545  /* transform contained query, allowing SELECT INTO */
2546  stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
2547 
2548  /* represent the command as a utility Query */
2549  result = makeNode(Query);
2550  result->commandType = CMD_UTILITY;
2551  result->utilityStmt = (Node *) stmt;
2552 
2553  return result;
2554 }
Definition: nodes.h:528
Node * utilityStmt
Definition: parsenodes.h:120
Node * query
Definition: parsenodes.h:3258
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:576
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:215

◆ transformInsertRow()

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

Definition at line 885 of file analyze.c.

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

Referenced by transformInsertStmt().

888 {
889  List *result;
890  ListCell *lc;
891  ListCell *icols;
892  ListCell *attnos;
893 
894  /*
895  * Check length of expr list. It must not have more expressions than
896  * there are target columns. We allow fewer, but only if no explicit
897  * columns list was given (the remaining columns are implicitly
898  * defaulted). Note we must check this *after* transformation because
899  * that could expand '*' into multiple items.
900  */
901  if (list_length(exprlist) > list_length(icolumns))
902  ereport(ERROR,
903  (errcode(ERRCODE_SYNTAX_ERROR),
904  errmsg("INSERT has more expressions than target columns"),
905  parser_errposition(pstate,
906  exprLocation(list_nth(exprlist,
907  list_length(icolumns))))));
908  if (stmtcols != NIL &&
909  list_length(exprlist) < list_length(icolumns))
910  {
911  /*
912  * We can get here for cases like INSERT ... SELECT (a,b,c) FROM ...
913  * where the user accidentally created a RowExpr instead of separate
914  * columns. Add a suitable hint if that seems to be the problem,
915  * because the main error message is quite misleading for this case.
916  * (If there's no stmtcols, you'll get something about data type
917  * mismatch, which is less misleading so we don't worry about giving a
918  * hint in that case.)
919  */
920  ereport(ERROR,
921  (errcode(ERRCODE_SYNTAX_ERROR),
922  errmsg("INSERT has more target columns than expressions"),
923  ((list_length(exprlist) == 1 &&
924  count_rowexpr_columns(pstate, linitial(exprlist)) ==
925  list_length(icolumns)) ?
926  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),
927  parser_errposition(pstate,
928  exprLocation(list_nth(icolumns,
929  list_length(exprlist))))));
930  }
931 
932  /*
933  * Prepare columns for assignment to target table.
934  */
935  result = NIL;
936  forthree(lc, exprlist, icols, icolumns, attnos, attrnos)
937  {
938  Expr *expr = (Expr *) lfirst(lc);
939  ResTarget *col = lfirst_node(ResTarget, icols);
940  int attno = lfirst_int(attnos);
941 
942  expr = transformAssignedExpr(pstate, expr,
944  col->name,
945  attno,
946  col->indirection,
947  col->location);
948 
949  if (strip_indirection)
950  {
951  while (expr)
952  {
953  if (IsA(expr, FieldStore))
954  {
955  FieldStore *fstore = (FieldStore *) expr;
956 
957  expr = (Expr *) linitial(fstore->newvals);
958  }
959  else if (IsA(expr, SubscriptingRef))
960  {
961  SubscriptingRef *sbsref = (SubscriptingRef *) expr;
962 
963  if (sbsref->refassgnexpr == NULL)
964  break;
965 
966  expr = sbsref->refassgnexpr;
967  }
968  else
969  break;
970  }
971  }
972 
973  result = lappend(result, expr);
974  }
975 
976  return result;
977 }
List * indirection
Definition: parsenodes.h:443
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
int errhint(const char *fmt,...)
Definition: elog.c:1068
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1240
Expr * transformAssignedExpr(ParseState *pstate, Expr *expr, ParseExprKind exprKind, const char *colname, int attrno, List *indirection, int location)
Definition: parse_target.c:450
char * name
Definition: parsenodes.h:442
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:479
static int count_rowexpr_columns(ParseState *pstate, Node *expr)
Definition: analyze.c:1148
int errcode(int sqlerrcode)
Definition: elog.c:610
int location
Definition: parsenodes.h:445
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:43
#define lfirst_int(lc)
Definition: pg_list.h:170
static void * list_nth(const List *list, int n)
Definition: pg_list.h:266
#define lfirst_node(type, lc)
Definition: pg_list.h:172
List * newvals
Definition: primnodes.h:795
List * lappend(List *list, void *datum)
Definition: list.c:321
#define ereport(elevel,...)
Definition: elog.h:144
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
Expr * refassgnexpr
Definition: primnodes.h:430
int errmsg(const char *fmt,...)
Definition: elog.c:821
Definition: pg_list.h:50

◆ transformInsertStmt()

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

Definition at line 467 of file analyze.c.

References ACL_INSERT, ACL_UPDATE, OnConflictClause::action, addNSItemToQuery(), addRangeTableEntryForSubquery(), addRangeTableEntryForValues(), 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, expandNSItemVars(), TargetEntry::expr, EXPR_KIND_VALUES, EXPR_KIND_VALUES_SINGLE, exprLocation(), exprType(), exprTypmod(), FirstLowInvalidHeapAttributeNumber, forthree, free_parsestate(), Query::hasModifyingCTE, Query::hasRecursive, InvalidOid, IsA, lappend(), lappend_int(), lappend_oid(), lfirst, lfirst_int, lfirst_node, SelectStmt::limitCount, SelectStmt::limitOffset, linitial, list_length(), 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_namespace, ParseState::p_resolve_unknowns, ParseState::p_rtable, parser_errposition(), WithClause::recursive, InsertStmt::relation, TargetEntry::resjunk, Query::resultRelation, InsertStmt::selectStmt, setTargetTable(), SelectStmt::sortClause, Query::targetList, transformExpressionList(), transformInsertRow(), transformOnConflictClause(), transformReturningList(), transformStmt(), transformWithClause(), val, SelectStmt::valuesLists, InsertStmt::withClause, and SelectStmt::withClause.

Referenced by transformStmt().

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

◆ transformLockingClause()

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

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

2772 {
2773  List *lockedRels = lc->lockedRels;
2774  ListCell *l;
2775  ListCell *rt;
2776  Index i;
2777  LockingClause *allrels;
2778 
2779  CheckSelectLocking(qry, lc->strength);
2780 
2781  /* make a clause we can pass down to subqueries to select all rels */
2782  allrels = makeNode(LockingClause);
2783  allrels->lockedRels = NIL; /* indicates all rels */
2784  allrels->strength = lc->strength;
2785  allrels->waitPolicy = lc->waitPolicy;
2786 
2787  if (lockedRels == NIL)
2788  {
2789  /* all regular tables used in query */
2790  i = 0;
2791  foreach(rt, qry->rtable)
2792  {
2793  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
2794 
2795  ++i;
2796  switch (rte->rtekind)
2797  {
2798  case RTE_RELATION:
2799  applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
2800  pushedDown);
2802  break;
2803  case RTE_SUBQUERY:
2804  applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
2805  pushedDown);
2806 
2807  /*
2808  * FOR UPDATE/SHARE of subquery is propagated to all of
2809  * subquery's rels, too. We could do this later (based on
2810  * the marking of the subquery RTE) but it is convenient
2811  * to have local knowledge in each query level about which
2812  * rels need to be opened with RowShareLock.
2813  */
2814  transformLockingClause(pstate, rte->subquery,
2815  allrels, true);
2816  break;
2817  default:
2818  /* ignore JOIN, SPECIAL, FUNCTION, VALUES, CTE RTEs */
2819  break;
2820  }
2821  }
2822  }
2823  else
2824  {
2825  /* just the named tables */
2826  foreach(l, lockedRels)
2827  {
2828  RangeVar *thisrel = (RangeVar *) lfirst(l);
2829 
2830  /* For simplicity we insist on unqualified alias names here */
2831  if (thisrel->catalogname || thisrel->schemaname)
2832  ereport(ERROR,
2833  (errcode(ERRCODE_SYNTAX_ERROR),
2834  /*------
2835  translator: %s is a SQL row locking clause such as FOR UPDATE */
2836  errmsg("%s must specify unqualified relation names",
2837  LCS_asString(lc->strength)),
2838  parser_errposition(pstate, thisrel->location)));
2839 
2840  i = 0;
2841  foreach(rt, qry->rtable)
2842  {
2843  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
2844 
2845  ++i;
2846  if (strcmp(rte->eref->aliasname, thisrel->relname) == 0)
2847  {
2848  switch (rte->rtekind)
2849  {
2850  case RTE_RELATION:
2851  applyLockingClause(qry, i, lc->strength,
2852  lc->waitPolicy, pushedDown);
2854  break;
2855  case RTE_SUBQUERY:
2856  applyLockingClause(qry, i, lc->strength,
2857  lc->waitPolicy, pushedDown);
2858  /* see comment above */
2859  transformLockingClause(pstate, rte->subquery,
2860  allrels, true);
2861  break;
2862  case RTE_JOIN:
2863  ereport(ERROR,
2864  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2865  /*------
2866  translator: %s is a SQL row locking clause such as FOR UPDATE */
2867  errmsg("%s cannot be applied to a join",
2868  LCS_asString(lc->strength)),
2869  parser_errposition(pstate, thisrel->location)));
2870  break;
2871  case RTE_FUNCTION:
2872  ereport(ERROR,
2873  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2874  /*------
2875  translator: %s is a SQL row locking clause such as FOR UPDATE */
2876  errmsg("%s cannot be applied to a function",
2877  LCS_asString(lc->strength)),
2878  parser_errposition(pstate, thisrel->location)));
2879  break;
2880  case RTE_TABLEFUNC:
2881  ereport(ERROR,
2882  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2883  /*------
2884  translator: %s is a SQL row locking clause such as FOR UPDATE */
2885  errmsg("%s cannot be applied to a table function",
2886  LCS_asString(lc->strength)),
2887  parser_errposition(pstate, thisrel->location)));
2888  break;
2889  case RTE_VALUES:
2890  ereport(ERROR,
2891  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2892  /*------
2893  translator: %s is a SQL row locking clause such as FOR UPDATE */
2894  errmsg("%s cannot be applied to VALUES",
2895  LCS_asString(lc->strength)),
2896  parser_errposition(pstate, thisrel->location)));
2897  break;
2898  case RTE_CTE:
2899  ereport(ERROR,
2900  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2901  /*------
2902  translator: %s is a SQL row locking clause such as FOR UPDATE */
2903  errmsg("%s cannot be applied to a WITH query",
2904  LCS_asString(lc->strength)),
2905  parser_errposition(pstate, thisrel->location)));
2906  break;
2907  case RTE_NAMEDTUPLESTORE:
2908  ereport(ERROR,
2909  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2910  /*------
2911  translator: %s is a SQL row locking clause such as FOR UPDATE */
2912  errmsg("%s cannot be applied to a named tuplestore",
2913  LCS_asString(lc->strength)),
2914  parser_errposition(pstate, thisrel->location)));
2915  break;
2916 
2917  /* Shouldn't be possible to see RTE_RESULT here */
2918 
2919  default:
2920  elog(ERROR, "unrecognized RTE type: %d",
2921  (int) rte->rtekind);
2922  break;
2923  }
2924  break; /* out of foreach loop */
2925  }
2926  }
2927  if (rt == NULL)
2928  ereport(ERROR,
2930  /*------
2931  translator: %s is a SQL row locking clause such as FOR UPDATE */
2932  errmsg("relation \"%s\" in %s clause not found in FROM clause",
2933  thisrel->relname,
2934  LCS_asString(lc->strength)),
2935  parser_errposition(pstate, thisrel->location)));
2936  }
2937  }
2938 }
List * lockedRels
Definition: parsenodes.h:751
#define NIL
Definition: pg_list.h:65
static void transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc, bool pushedDown)
Definition: analyze.c:2770
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2681
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:74
int errcode(int sqlerrcode)
Definition: elog.c:610
AclMode requiredPerms
Definition: parsenodes.h:1120
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:2706
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
LockClauseStrength strength
Definition: parsenodes.h:752
unsigned int Index
Definition: c.h:483
#define ereport(elevel,...)
Definition: elog.h:144
#define makeNode(_type_)
Definition: nodes.h:576
#define lfirst(lc)
Definition: pg_list.h:169
char * aliasname
Definition: primnodes.h:42
#define ACL_SELECT_FOR_UPDATE
Definition: parsenodes.h:90
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
RTEKind rtekind
Definition: parsenodes.h:977
Query * subquery
Definition: parsenodes.h:1012
int errmsg(const char *fmt,...)
Definition: elog.c:821
#define elog(elevel,...)
Definition: elog.h:214
int i
Alias * eref
Definition: parsenodes.h:1116
Definition: pg_list.h:50
LockWaitPolicy waitPolicy
Definition: parsenodes.h:753
char * catalogname
Definition: primnodes.h:66
void applyLockingClause(Query *qry, Index rtindex, LockClauseStrength strength, LockWaitPolicy waitPolicy, bool pushedDown)
Definition: analyze.c:2944

◆ transformOnConflictClause()

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

Definition at line 984 of file analyze.c.

References OnConflictClause::action, OnConflictExpr::action, addNSItemToQuery(), addRangeTableEntryForRelation(), OnConflictExpr::arbiterElems, OnConflictExpr::arbiterWhere, BuildOnConflictExcludedTargetlist(), OnConflictExpr::constraint, OnConflictExpr::exclRelIndex, OnConflictExpr::exclRelTlist, EXPR_KIND_WHERE, makeAlias(), makeNode, NIL, ONCONFLICT_UPDATE, OnConflictExpr::onConflictSet, OnConflictExpr::onConflictWhere, ParseState::p_is_insert, ParseNamespaceItem::p_rte, ParseNamespaceItem::p_rtindex, ParseState::p_target_nsitem, ParseState::p_target_relation, RangeTblEntry::relkind, RangeTblEntry::requiredPerms, RowExclusiveLock, OnConflictClause::targetList, transformOnConflictArbiter(), transformUpdateTargetList(), transformWhereClause(), and OnConflictClause::whereClause.

Referenced by transformInsertStmt().

986 {
987  List *arbiterElems;
988  Node *arbiterWhere;
989  Oid arbiterConstraint;
990  List *onConflictSet = NIL;
991  Node *onConflictWhere = NULL;
992  int exclRelIndex = 0;
993  List *exclRelTlist = NIL;
994  OnConflictExpr *result;
995 
996  /* Process the arbiter clause, ON CONFLICT ON (...) */
997  transformOnConflictArbiter(pstate, onConflictClause, &arbiterElems,
998  &arbiterWhere, &arbiterConstraint);
999 
1000  /* Process DO UPDATE */
1001  if (onConflictClause->action == ONCONFLICT_UPDATE)
1002  {
1003  Relation targetrel = pstate->p_target_relation;
1004  ParseNamespaceItem *exclNSItem;
1005  RangeTblEntry *exclRte;
1006 
1007  /*
1008  * All INSERT expressions have been parsed, get ready for potentially
1009  * existing SET statements that need to be processed like an UPDATE.
1010  */
1011  pstate->p_is_insert = false;
1012 
1013  /*
1014  * Add range table entry for the EXCLUDED pseudo relation. relkind is
1015  * set to composite to signal that we're not dealing with an actual
1016  * relation, and no permission checks are required on it. (We'll
1017  * check the actual target relation, instead.)
1018  */
1019  exclNSItem = addRangeTableEntryForRelation(pstate,
1020  targetrel,
1022  makeAlias("excluded", NIL),
1023  false, false);
1024  exclRte = exclNSItem->p_rte;
1025  exclRelIndex = exclNSItem->p_rtindex;
1026 
1027  exclRte->relkind = RELKIND_COMPOSITE_TYPE;
1028  exclRte->requiredPerms = 0;
1029  /* other permissions fields in exclRte are already empty */
1030 
1031  /* Create EXCLUDED rel's targetlist for use by EXPLAIN */
1032  exclRelTlist = BuildOnConflictExcludedTargetlist(targetrel,
1033  exclRelIndex);
1034 
1035  /*
1036  * Add EXCLUDED and the target RTE to the namespace, so that they can
1037  * be used in the UPDATE subexpressions.
1038  */
1039  addNSItemToQuery(pstate, exclNSItem, false, true, true);
1040  addNSItemToQuery(pstate, pstate->p_target_nsitem,
1041  false, true, true);
1042 
1043  /*
1044  * Now transform the UPDATE subexpressions.
1045  */
1046  onConflictSet =
1047  transformUpdateTargetList(pstate, onConflictClause->targetList);
1048 
1049  onConflictWhere = transformWhereClause(pstate,
1050  onConflictClause->whereClause,
1051  EXPR_KIND_WHERE, "WHERE");
1052  }
1053 
1054  /* Finally, build ON CONFLICT DO [NOTHING | UPDATE] expression */
1055  result = makeNode(OnConflictExpr);
1056 
1057  result->action = onConflictClause->action;
1058  result->arbiterElems = arbiterElems;
1059  result->arbiterWhere = arbiterWhere;
1060  result->constraint = arbiterConstraint;
1061  result->onConflictSet = onConflictSet;
1062  result->onConflictWhere = onConflictWhere;
1063  result->exclRelIndex = exclRelIndex;
1064  result->exclRelTlist = exclRelTlist;
1065 
1066  return result;
1067 }
#define NIL
Definition: pg_list.h:65
static List * transformUpdateTargetList(ParseState *pstate, List *targetList)
Definition: analyze.c:2293
List * BuildOnConflictExcludedTargetlist(Relation targetrel, Index exclRelIndex)
Definition: analyze.c:1078
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:528
void transformOnConflictArbiter(ParseState *pstate, OnConflictClause *onConflictClause, List **arbiterExpr, Node **arbiterWhere, Oid *constraint)
ParseNamespaceItem * p_target_nsitem
Definition: parse_node.h:191
AclMode requiredPerms
Definition: parsenodes.h:1120
unsigned int Oid
Definition: postgres_ext.h:31
List * arbiterElems
Definition: primnodes.h:1532
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:387
RangeTblEntry * p_rte
Definition: parse_node.h:257
List * exclRelTlist
Definition: primnodes.h:1541
#define RowExclusiveLock
Definition: lockdefs.h:38
OnConflictAction action
Definition: primnodes.h:1529
#define makeNode(_type_)
Definition: nodes.h:576
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
Node * arbiterWhere
Definition: primnodes.h:1534
Relation p_target_relation
Definition: parse_node.h:190
bool p_is_insert
Definition: parse_node.h:192
List * onConflictSet
Definition: primnodes.h:1538
Node * onConflictWhere
Definition: primnodes.h:1539
OnConflictAction action
Definition: parsenodes.h:1428
Definition: pg_list.h:50

◆ transformOptionalSelectInto()

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

Definition at line 215 of file analyze.c.

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

Referenced by transformExplainStmt(), and transformTopLevelStmt().

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

◆ transformReturningList()

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

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

2399 {
2400  List *rlist;
2401  int save_next_resno;
2402 
2403  if (returningList == NIL)
2404  return NIL; /* nothing to do */
2405 
2406  /*
2407  * We need to assign resnos starting at one in the RETURNING list. Save
2408  * and restore the main tlist's value of p_next_resno, just in case
2409  * someone looks at it later (probably won't happen).
2410  */
2411  save_next_resno = pstate->p_next_resno;
2412  pstate->p_next_resno = 1;
2413 
2414  /* transform RETURNING identically to a SELECT targetlist */
2415  rlist = transformTargetList(pstate, returningList, EXPR_KIND_RETURNING);
2416 
2417  /*
2418  * Complain if the nonempty tlist expanded to nothing (which is possible
2419  * if it contains only a star-expansion of a zero-column table). If we
2420  * allow this, the parsed Query will look like it didn't have RETURNING,
2421  * with results that would probably surprise the user.
2422  */
2423  if (rlist == NIL)
2424  ereport(ERROR,
2425  (errcode(ERRCODE_SYNTAX_ERROR),
2426  errmsg("RETURNING must have at least one column"),
2427  parser_errposition(pstate,
2428  exprLocation(linitial(returningList)))));
2429 
2430  /* mark column origins */
2431  markTargetListOrigins(pstate, rlist);
2432 
2433  /* resolve any still-unresolved output columns as being type text */
2434  if (pstate->p_resolve_unknowns)
2435  resolveTargetListUnknowns(pstate, rlist);
2436 
2437  /* restore state */
2438  pstate->p_next_resno = save_next_resno;
2439 
2440  return rlist;
2441 }
#define NIL
Definition: pg_list.h:65
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1240
int errcode(int sqlerrcode)
Definition: elog.c:610
List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind)
Definition: parse_target.c:133
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:43
bool p_resolve_unknowns
Definition: parse_node.h:200
int p_next_resno
Definition: parse_node.h:195
void resolveTargetListUnknowns(ParseState *pstate, List *targetlist)
Definition: parse_target.c:301
#define ereport(elevel,...)
Definition: elog.h:144
void markTargetListOrigins(ParseState *pstate, List *targetlist)
Definition: parse_target.c:331
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
int errmsg(const char *fmt,...)
Definition: elog.c:821
Definition: pg_list.h:50

◆ transformSelectStmt()

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

Definition at line 1190 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, Query::limitOption, SelectStmt::limitOption, 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().

1191 {
1192  Query *qry = makeNode(Query);
1193  Node *qual;
1194  ListCell *l;
1195 
1196  qry->commandType = CMD_SELECT;
1197 
1198  /* process the WITH clause independently of all else */
1199  if (stmt->withClause)
1200  {
1201  qry->hasRecursive = stmt->withClause->recursive;
1202  qry->cteList = transformWithClause(pstate, stmt->withClause);
1203  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1204  }
1205 
1206  /* Complain if we get called from someplace where INTO is not allowed */
1207  if (stmt->intoClause)
1208  ereport(ERROR,
1209  (errcode(ERRCODE_SYNTAX_ERROR),
1210  errmsg("SELECT ... INTO is not allowed here"),
1211  parser_errposition(pstate,
1212  exprLocation((Node *) stmt->intoClause))));
1213 
1214  /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
1215  pstate->p_locking_clause = stmt->lockingClause;
1216 
1217  /* make WINDOW info available for window functions, too */
1218  pstate->p_windowdefs = stmt->windowClause;
1219 
1220  /* process the FROM clause */
1221  transformFromClause(pstate, stmt->fromClause);
1222 
1223  /* transform targetlist */
1224  qry->targetList = transformTargetList(pstate, stmt->targetList,
1226 
1227  /* mark column origins */
1228  markTargetListOrigins(pstate, qry->targetList);
1229 
1230  /* transform WHERE */
1231  qual = transformWhereClause(pstate, stmt->whereClause,
1232  EXPR_KIND_WHERE, "WHERE");
1233 
1234  /* initial processing of HAVING clause is much like WHERE clause */
1235  qry->havingQual = transformWhereClause(pstate, stmt->havingClause,
1236  EXPR_KIND_HAVING, "HAVING");
1237 
1238  /*
1239  * Transform sorting/grouping stuff. Do ORDER BY first because both
1240  * transformGroupClause and transformDistinctClause need the results. Note
1241  * that these functions can also change the targetList, so it's passed to
1242  * them by reference.
1243  */
1244  qry->sortClause = transformSortClause(pstate,
1245  stmt->sortClause,
1246  &qry->targetList,
1248  false /* allow SQL92 rules */ );
1249 
1250  qry->groupClause = transformGroupClause(pstate,
1251  stmt->groupClause,
1252  &qry->groupingSets,
1253  &qry->targetList,
1254  qry->sortClause,
1256  false /* allow SQL92 rules */ );
1257 
1258  if (stmt->distinctClause == NIL)
1259  {
1260  qry->distinctClause = NIL;
1261  qry->hasDistinctOn = false;
1262  }
1263  else if (linitial(stmt->distinctClause) == NULL)
1264  {
1265  /* We had SELECT DISTINCT */
1267  &qry->targetList,
1268  qry->sortClause,
1269  false);
1270  qry->hasDistinctOn = false;
1271  }
1272  else
1273  {
1274  /* We had SELECT DISTINCT ON */
1276  stmt->distinctClause,
1277  &qry->targetList,
1278  qry->sortClause);
1279  qry->hasDistinctOn = true;
1280  }
1281 
1282  /* transform LIMIT */
1283  qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
1284  EXPR_KIND_OFFSET, "OFFSET",
1285  stmt->limitOption);
1286  qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
1287  EXPR_KIND_LIMIT, "LIMIT",
1288  stmt->limitOption);
1289  qry->limitOption = stmt->limitOption;
1290 
1291  /* transform window clauses after we have seen all window functions */
1293  pstate->p_windowdefs,
1294  &qry->targetList);
1295 
1296  /* resolve any still-unresolved output columns as being type text */
1297  if (pstate->p_resolve_unknowns)
1298  resolveTargetListUnknowns(pstate, qry->targetList);
1299 
1300  qry->rtable = pstate->p_rtable;
1301  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
1302 
1303  qry->hasSubLinks = pstate->p_hasSubLinks;
1304  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
1305  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
1306  qry->hasAggs = pstate->p_hasAggs;
1307 
1308  foreach(l, stmt->lockingClause)
1309  {
1310  transformLockingClause(pstate, qry,
1311  (LockingClause *) lfirst(l), false);
1312  }
1313 
1314  assign_query_collations(pstate, qry);
1315 
1316  /* this must be done after collations, for reliable comparison of exprs */
1317  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
1318  parseCheckAggregates(pstate, qry);
1319 
1320  return qry;
1321 }
Node * limitOffset
Definition: parsenodes.h:160
#define NIL
Definition: pg_list.h:65
LimitOption limitOption
Definition: parsenodes.h:1622
static void transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc, bool pushedDown)
Definition: analyze.c:2770
bool p_hasSubLinks
Definition: parse_node.h:209
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:285
List * sortClause
Definition: parsenodes.h:158
List * transformDistinctOnClause(ParseState *pstate, List *distinctlist, List **targetlist, List *sortClause)
IntoClause * intoClause
Definition: parsenodes.h:1597
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1240
List * fromClause
Definition: parsenodes.h:1599
FromExpr * jointree
Definition: parsenodes.h:138
List * transformSortClause(ParseState *pstate, List *orderlist, List **targetlist, ParseExprKind exprKind, bool useSQL99)
Node * limitOffset
Definition: parsenodes.h:1620
bool hasAggs
Definition: parsenodes.h:125
bool p_hasTargetSRFs
Definition: parse_node.h:208
List * groupingSets
Definition: parsenodes.h:150
Definition: nodes.h:528
int errcode(int sqlerrcode)
Definition: elog.c:610
bool p_hasAggs
Definition: parse_node.h:206
void parseCheckAggregates(ParseState *pstate, Query *qry)
Definition: parse_agg.c:1042
bool hasDistinctOn
Definition: parsenodes.h:129
List * windowClause
Definition: parsenodes.h:154
List * targetList
Definition: parsenodes.h:140
bool p_hasWindowFuncs
Definition: parse_node.h:207
bool hasRecursive
Definition: parsenodes.h:130
List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind)
Definition: parse_target.c:133
List * distinctClause
Definition: parsenodes.h:1595
#define linitial(l)
Definition: pg_list.h:174
List * rtable
Definition: parsenodes.h:137
List * distinctClause
Definition: parsenodes.h:156
#define ERROR
Definition: elog.h:43
Node * transformLimitClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName, LimitOption limitOption)
List * p_windowdefs
Definition: parse_node.h:193
bool p_resolve_unknowns
Definition: parse_node.h:200
Node * limitCount
Definition: parsenodes.h:161
List * sortClause
Definition: parsenodes.h:1619
List * targetList
Definition: parsenodes.h:1598
List * transformGroupClause(ParseState *pstate, List *grouplist, List **groupingSets, List **targetlist, List *sortClause, ParseExprKind exprKind, bool useSQL99)
List * p_locking_clause
Definition: parse_node.h:197
bool recursive
Definition: parsenodes.h:1400
List * lockingClause
Definition: parsenodes.h:1623
bool p_hasModifyingCTE
Definition: parse_node.h:210
LimitOption limitOption
Definition: parsenodes.h:162
List * transformWindowDefinitions(ParseState *pstate, List *windowdefs, List **targetlist)
void resolveTargetListUnknowns(ParseState *pstate, List *targetlist)
Definition: parse_target.c:301
void transformFromClause(ParseState *pstate, List *frmList)
Definition: parse_clause.c:114
List * windowClause
Definition: parsenodes.h:1603
#define ereport(elevel,...)
Definition: elog.h:144
CmdType commandType
Definition: parsenodes.h:112
bool hasTargetSRFs
Definition: parsenodes.h:127
#define makeNode(_type_)
Definition: nodes.h:576
#define lfirst(lc)
Definition: pg_list.h:169
bool hasWindowFuncs
Definition: parsenodes.h:126
void markTargetListOrigins(ParseState *pstate, List *targetlist)
Definition: parse_target.c:331
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:110
List * groupClause
Definition: parsenodes.h:1601
List * cteList
Definition: parsenodes.h:135
List * groupClause
Definition: parsenodes.h:148
int errmsg(const char *fmt,...)
Definition: elog.c:821
bool hasSubLinks
Definition: parsenodes.h:128
void assign_query_collations(ParseState *pstate, Query *query)
Node * havingClause
Definition: parsenodes.h:1602
List * p_joinlist
Definition: parse_node.h:182
bool hasModifyingCTE
Definition: parsenodes.h:131
WithClause * withClause
Definition: parsenodes.h:1624
List * transformDistinctClause(ParseState *pstate, List **targetlist, List *sortClause, bool is_agg)
Node * havingQual
Definition: parsenodes.h:152
Node * limitCount
Definition: parsenodes.h:1621
Node * whereClause
Definition: parsenodes.h:1600
List * p_rtable
Definition: parse_node.h:180

◆ transformSetOperationStmt()

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

Definition at line 1567 of file analyze.c.

References addNSItemToQuery(), addRangeTableEntryForJoin(), 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(), forfour, 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, Query::limitOption, SelectStmt::limitOption, linitial, list_length(), list_nth(), list_truncate(), 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, ParseNamespaceColumn::p_varattno, ParseNamespaceColumn::p_varattnosyn, ParseNamespaceColumn::p_varcollid, ParseNamespaceColumn::p_varno, ParseNamespaceColumn::p_varnosyn, ParseNamespaceColumn::p_vartype, ParseNamespaceColumn::p_vartypmod, palloc0(), 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().

1568 {
1569  Query *qry = makeNode(Query);
1570  SelectStmt *leftmostSelect;
1571  int leftmostRTI;
1572  Query *leftmostQuery;
1573  SetOperationStmt *sostmt;
1574  List *sortClause;
1575  Node *limitOffset;
1576  Node *limitCount;
1577  List *lockingClause;
1578  WithClause *withClause;
1579  Node *node;
1580  ListCell *left_tlist,
1581  *lct,
1582  *lcm,
1583  *lcc,
1584  *l;
1585  List *targetvars,
1586  *targetnames,
1587  *sv_namespace;
1588  int sv_rtable_length;
1589  ParseNamespaceItem *jnsitem;
1590  ParseNamespaceColumn *sortnscolumns;
1591  int sortcolindex;
1592  int tllen;
1593 
1594  qry->commandType = CMD_SELECT;
1595 
1596  /*
1597  * Find leftmost leaf SelectStmt. We currently only need to do this in
1598  * order to deliver a suitable error message if there's an INTO clause
1599  * there, implying the set-op tree is in a context that doesn't allow
1600  * INTO. (transformSetOperationTree would throw error anyway, but it
1601  * seems worth the trouble to throw a different error for non-leftmost
1602  * INTO, so we produce that error in transformSetOperationTree.)
1603  */
1604  leftmostSelect = stmt->larg;
1605  while (leftmostSelect && leftmostSelect->op != SETOP_NONE)
1606  leftmostSelect = leftmostSelect->larg;
1607  Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
1608  leftmostSelect->larg == NULL);
1609  if (leftmostSelect->intoClause)
1610  ereport(ERROR,
1611  (errcode(ERRCODE_SYNTAX_ERROR),
1612  errmsg("SELECT ... INTO is not allowed here"),
1613  parser_errposition(pstate,
1614  exprLocation((Node *) leftmostSelect->intoClause))));
1615 
1616  /*
1617  * We need to extract ORDER BY and other top-level clauses here and not
1618  * let transformSetOperationTree() see them --- else it'll just recurse
1619  * right back here!
1620  */
1621  sortClause = stmt->sortClause;
1622  limitOffset = stmt->limitOffset;
1623  limitCount = stmt->limitCount;
1624  lockingClause = stmt->lockingClause;
1625  withClause = stmt->withClause;
1626 
1627  stmt->sortClause = NIL;
1628  stmt->limitOffset = NULL;
1629  stmt->limitCount = NULL;
1630  stmt->lockingClause = NIL;
1631  stmt->withClause = NULL;
1632 
1633  /* We don't support FOR UPDATE/SHARE with set ops at the moment. */
1634  if (lockingClause)
1635  ereport(ERROR,
1636  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1637  /*------
1638  translator: %s is a SQL row locking clause such as FOR UPDATE */
1639  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
1641  linitial(lockingClause))->strength))));
1642 
1643  /* Process the WITH clause independently of all else */
1644  if (withClause)
1645  {
1646  qry->hasRecursive = withClause->recursive;
1647  qry->cteList = transformWithClause(pstate, withClause);
1648  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1649  }
1650 
1651  /*
1652  * Recursively transform the components of the tree.
1653  */
1654  sostmt = castNode(SetOperationStmt,
1655  transformSetOperationTree(pstate, stmt, true, NULL));
1656  Assert(sostmt);
1657  qry->setOperations = (Node *) sostmt;
1658 
1659  /*
1660  * Re-find leftmost SELECT (now it's a sub-query in rangetable)
1661  */
1662  node = sostmt->larg;
1663  while (node && IsA(node, SetOperationStmt))
1664  node = ((SetOperationStmt *) node)->larg;
1665  Assert(node && IsA(node, RangeTblRef));
1666  leftmostRTI = ((RangeTblRef *) node)->rtindex;
1667  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
1668  Assert(leftmostQuery != NULL);
1669 
1670  /*
1671  * Generate dummy targetlist for outer query using column names of
1672  * leftmost select and common datatypes/collations of topmost set
1673  * operation. Also make lists of the dummy vars and their names for use
1674  * in parsing ORDER BY.
1675  *
1676  * Note: we use leftmostRTI as the varno of the dummy variables. It
1677  * shouldn't matter too much which RT index they have, as long as they
1678  * have one that corresponds to a real RT entry; else funny things may
1679  * happen when the tree is mashed by rule rewriting.
1680  */
1681  qry->targetList = NIL;
1682  targetvars = NIL;
1683  targetnames = NIL;
1684  sortnscolumns = (ParseNamespaceColumn *)
1685  palloc0(list_length(sostmt->colTypes) * sizeof(ParseNamespaceColumn));
1686  sortcolindex = 0;
1687 
1688  forfour(lct, sostmt->colTypes,
1689  lcm, sostmt->colTypmods,
1690  lcc, sostmt->colCollations,
1691  left_tlist, leftmostQuery->targetList)
1692  {
1693  Oid colType = lfirst_oid(lct);
1694  int32 colTypmod = lfirst_int(lcm);
1695  Oid colCollation = lfirst_oid(lcc);
1696  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
1697  char *colName;
1698  TargetEntry *tle;
1699  Var *var;
1700 
1701  Assert(!lefttle->resjunk);
1702  colName = pstrdup(lefttle->resname);
1703  var = makeVar(leftmostRTI,
1704  lefttle->resno,
1705  colType,
1706  colTypmod,
1707  colCollation,
1708  0);
1709  var->location = exprLocation((Node *) lefttle->expr);
1710  tle = makeTargetEntry((Expr *) var,
1711  (AttrNumber) pstate->p_next_resno++,
1712  colName,
1713  false);
1714  qry->targetList = lappend(qry->targetList, tle);
1715  targetvars = lappend(targetvars, var);
1716  targetnames = lappend(targetnames, makeString(colName));
1717  sortnscolumns[sortcolindex].p_varno = leftmostRTI;
1718  sortnscolumns[sortcolindex].p_varattno = lefttle->resno;
1719  sortnscolumns[sortcolindex].p_vartype = colType;
1720  sortnscolumns[sortcolindex].p_vartypmod = colTypmod;
1721  sortnscolumns[sortcolindex].p_varcollid = colCollation;
1722  sortnscolumns[sortcolindex].p_varnosyn = leftmostRTI;
1723  sortnscolumns[sortcolindex].p_varattnosyn = lefttle->resno;
1724  sortcolindex++;
1725  }
1726 
1727  /*
1728  * As a first step towards supporting sort clauses that are expressions
1729  * using the output columns, generate a namespace entry that makes the
1730  * output columns visible. A Join RTE node is handy for this, since we
1731  * can easily control the Vars generated upon matches.
1732  *
1733  * Note: we don't yet do anything useful with such cases, but at least
1734  * "ORDER BY upper(foo)" will draw the right error message rather than
1735  * "foo not found".
1736  */
1737  sv_rtable_length = list_length(pstate->p_rtable);
1738 
1739  jnsitem = addRangeTableEntryForJoin(pstate,
1740  targetnames,
1741  sortnscolumns,
1742  JOIN_INNER,
1743  0,
1744  targetvars,
1745  NIL,
1746  NIL,
1747  NULL,
1748  false);
1749 
1750  sv_namespace = pstate->p_namespace;
1751  pstate->p_namespace = NIL;
1752 
1753  /* add jnsitem to column namespace only */
1754  addNSItemToQuery(pstate, jnsitem, false, false, true);
1755 
1756  /*
1757  * For now, we don't support resjunk sort clauses on the output of a
1758  * setOperation tree --- you can only use the SQL92-spec options of
1759  * selecting an output column by name or number. Enforce by checking that
1760  * transformSortClause doesn't add any items to tlist.
1761  */
1762  tllen = list_length(qry->targetList);
1763 
1764  qry->sortClause = transformSortClause(pstate,
1765  sortClause,
1766  &qry->targetList,
1768  false /* allow SQL92 rules */ );
1769 
1770  /* restore namespace, remove join RTE from rtable */
1771  pstate->p_namespace = sv_namespace;
1772  pstate->p_rtable = list_truncate(pstate->p_rtable, sv_rtable_length);
1773 
1774  if (tllen != list_length(qry->targetList))
1775  ereport(ERROR,
1776  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1777  errmsg("invalid UNION/INTERSECT/EXCEPT ORDER BY clause"),
1778  errdetail("Only result column names can be used, not expressions or functions."),
1779  errhint("Add the expression/function to every SELECT, or move the UNION into a FROM clause."),
1780  parser_errposition(pstate,
1781  exprLocation(list_nth(qry->targetList, tllen)))));
1782 
1783  qry->limitOffset = transformLimitClause(pstate, limitOffset,
1784  EXPR_KIND_OFFSET, "OFFSET",
1785  stmt->limitOption);
1786  qry->limitCount = transformLimitClause(pstate, limitCount,
1787  EXPR_KIND_LIMIT, "LIMIT",
1788  stmt->limitOption);
1789  qry->limitOption = stmt->limitOption;
1790 
1791  qry->rtable = pstate->p_rtable;
1792  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
1793 
1794  qry->hasSubLinks = pstate->p_hasSubLinks;
1795  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
1796  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
1797  qry->hasAggs = pstate->p_hasAggs;
1798 
1799  foreach(l, lockingClause)
1800  {
1801  transformLockingClause(pstate, qry,
1802  (LockingClause *) lfirst(l), false);
1803  }
1804 
1805  assign_query_collations(pstate, qry);
1806 
1807  /* this must be done after collations, for reliable comparison of exprs */
1808  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
1809  parseCheckAggregates(pstate, qry);
1810 
1811  return qry;
1812 }
Value * makeString(char *str)
Definition: value.c:53
struct ParseNamespaceColumn ParseNamespaceColumn
Definition: parse_node.h:25
Node * limitOffset
Definition: parsenodes.h:160
#define NIL
Definition: pg_list.h:65
struct SelectStmt * larg
Definition: parsenodes.h:1631
LimitOption limitOption
Definition: parsenodes.h:1622
static void transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc, bool pushedDown)
Definition: analyze.c:2770
bool p_hasSubLinks
Definition: parse_node.h:209
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:285
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2681
int errhint(const char *fmt,...)
Definition: elog.c:1068
List * sortClause
Definition: parsenodes.h:158
IntoClause * intoClause
Definition: parsenodes.h:1597
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1240
FromExpr * jointree
Definition: parsenodes.h:138
#define castNode(_type_, nodeptr)
Definition: nodes.h:597
List * transformSortClause(ParseState *pstate, List *orderlist, List **targetlist, ParseExprKind exprKind, bool useSQL99)
Node * limitOffset
Definition: parsenodes.h:1620
char * pstrdup(const char *in)
Definition: mcxt.c:1187
bool hasAggs
Definition: parsenodes.h:125
List * list_truncate(List *list, int new_size)
Definition: list.c:585
bool p_hasTargetSRFs
Definition: parse_node.h:208
List * groupingSets
Definition: parsenodes.h:150
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
Definition: nodes.h:528
int errcode(int sqlerrcode)
Definition: elog.c:610
bool p_hasAggs
Definition: parse_node.h:206
unsigned int Oid
Definition: postgres_ext.h:31
char * resname
Definition: primnodes.h:1412
Definition: primnodes.h:181
void parseCheckAggregates(ParseState *pstate, Query *qry)
Definition: parse_agg.c:1042
signed int int32
Definition: c.h:363
List * targetList
Definition: parsenodes.h:140
bool p_hasWindowFuncs
Definition: parse_node.h:207
bool hasRecursive
Definition: parsenodes.h:130
bool resjunk
Definition: primnodes.h:1417
#define linitial(l)
Definition: pg_list.h:174
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
Node * transformLimitClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName, LimitOption limitOption)
#define lfirst_int(lc)
Definition: pg_list.h:170
static void * list_nth(const List *list, int n)
Definition: pg_list.h:266
int location
Definition: primnodes.h:196
Node * limitCount
Definition: parsenodes.h:161
AttrNumber p_varattno
Definition: parse_node.h:291
List * p_namespace
Definition: parse_node.h:184
List * sortClause
Definition: parsenodes.h:1619
int errdetail(const char *fmt,...)
Definition: elog.c:954
AttrNumber resno
Definition: primnodes.h:1411
int p_next_resno
Definition: parse_node.h:195
bool recursive
Definition: parsenodes.h:1400
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
static Node * transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, bool isTopLevel, List **targetlist)
Definition: analyze.c:1829
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
List * lockingClause
Definition: parsenodes.h:1623
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
bool p_hasModifyingCTE
Definition: parse_node.h:210
List * lappend(List *list, void *datum)
Definition: list.c:321
LimitOption limitOption
Definition: parsenodes.h:162
List * colCollations
Definition: parsenodes.h:1668
void * palloc0(Size size)
Definition: mcxt.c:981
SetOperation op
Definition: parsenodes.h:1629
#define ereport(elevel,...)
Definition: elog.h:144
CmdType commandType
Definition: parsenodes.h:112
bool hasTargetSRFs
Definition: parsenodes.h:127
#define makeNode(_type_)
Definition: nodes.h:576
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
bool hasWindowFuncs
Definition: parsenodes.h:126
Expr * expr
Definition: primnodes.h:1410
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
static int list_length(const List *l)
Definition: pg_list.h:149
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
Definition: pg_list.h:491
List * cteList
Definition: parsenodes.h:135
Node * setOperations
Definition: parsenodes.h:166
List * groupClause
Definition: parsenodes.h:148
int errmsg(const char *fmt,...)
Definition: elog.c:821
bool hasSubLinks
Definition: parsenodes.h:128
void assign_query_collations(ParseState *pstate, Query *query)
AttrNumber p_varattnosyn
Definition: parse_node.h:296
List * p_joinlist
Definition: parse_node.h:182
bool hasModifyingCTE
Definition: parsenodes.h:131
ParseNamespaceItem * addRangeTableEntryForJoin(ParseState *pstate, List *colnames, ParseNamespaceColumn *nscolumns, JoinType jointype, int nummergedcols, List *aliasvars, List *leftcols, List *rightcols, Alias *alias, bool inFromCl)
WithClause * withClause
Definition: parsenodes.h:1624
Node * havingQual
Definition: parsenodes.h:152
Definition: pg_list.h:50
int16 AttrNumber
Definition: attnum.h:21
Node * limitCount
Definition: parsenodes.h:1621
#define lfirst_oid(lc)
Definition: pg_list.h:171
List * p_rtable
Definition: parse_node.h:180

◆ transformSetOperationTree()

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

Definition at line 1829 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, ParseNamespaceItem::p_rtindex, parse_sub_analyze(), parser_errposition(), SelectStmt::rarg, SetOperationStmt::rarg, TargetEntry::resjunk, RangeTblRef::rtindex, select_common_collation(), select_common_type(), SETOP_INTERSECT, SETOP_NONE, SETOP_UNION, setup_parser_errposition_callback(), snprintf, SelectStmt::sortClause, SortGroupClause::sortop, Query::targetList, SortGroupClause::tleSortGroupRef, SetToDefault::typeId, SetToDefault::typeMod, and SelectStmt::withClause.

Referenced by transformSetOperationStmt().

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

◆ transformStmt()

Query* transformStmt ( ParseState pstate,
Node parseTree 
)

Definition at line 254 of file analyze.c.

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

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

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

◆ transformTopLevelStmt()

Query* transformTopLevelStmt ( ParseState pstate,
RawStmt parseTree 
)

Definition at line 191 of file analyze.c.

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

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

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

◆ transformUpdateStmt()

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

Definition at line 2229 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, 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_rtable, ParseState::p_target_nsitem, 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().

2230 {
2231  Query *qry = makeNode(Query);
2232  ParseNamespaceItem *nsitem;
2233  Node *qual;
2234 
2235  qry->commandType = CMD_UPDATE;
2236  pstate->p_is_insert = false;
2237 
2238  /* process the WITH clause independently of all else */
2239  if (stmt->withClause)
2240  {
2241  qry->hasRecursive = stmt->withClause->recursive;
2242  qry->cteList = transformWithClause(pstate, stmt->withClause);
2243  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
2244  }
2245 
2246  qry->resultRelation = setTargetTable(pstate, stmt->relation,
2247  stmt->relation->inh,
2248  true,
2249  ACL_UPDATE);
2250  nsitem = pstate->p_target_nsitem;
2251 
2252  /* subqueries in FROM cannot access the result relation */
2253  nsitem->p_lateral_only = true;
2254  nsitem->p_lateral_ok = false;
2255 
2256  /*
2257  * the FROM clause is non-standard SQL syntax. We used to be able to do
2258  * this with REPLACE in POSTQUEL so we keep the feature.
2259  */
2260  transformFromClause(pstate, stmt->fromClause);
2261 
2262  /* remaining clauses can reference the result relation normally */
2263  nsitem->p_lateral_only = false;
2264  nsitem->p_lateral_ok = true;
2265 
2266  qual = transformWhereClause(pstate, stmt->whereClause,
2267  EXPR_KIND_WHERE, "WHERE");
2268 
2269  qry->returningList = transformReturningList(pstate, stmt->returningList);
2270 
2271  /*
2272  * Now we are done with SELECT-like processing, and can get on with
2273  * transforming the target list to match the UPDATE target columns.
2274  */
2275  qry->targetList = transformUpdateTargetList(pstate, stmt->targetList);
2276 
2277  qry->rtable = pstate->p_rtable;
2278  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2279 
2280  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2281  qry->hasSubLinks = pstate->p_hasSubLinks;
2282 
2283  assign_query_collations(pstate, qry);
2284 
2285  return qry;
2286 }
List * fromClause
Definition: parsenodes.h:1562
bool p_hasSubLinks
Definition: parse_node.h:209
static List * transformUpdateTargetList(ParseState *pstate, List *targetList)
Definition: analyze.c:2293
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:285
FromExpr * jointree
Definition: parsenodes.h:138
int resultRelation
Definition: parsenodes.h:122
bool p_hasTargetSRFs
Definition: parse_node.h:208
Definition: nodes.h:528
List * targetList
Definition: parsenodes.h:1560
static List * transformReturningList(ParseState *pstate, List *returningList)
Definition: analyze.c:2398
ParseNamespaceItem * p_target_nsitem
Definition: parse_node.h:191
Node * whereClause
Definition: parsenodes.h:1561
List * targetList
Definition: parsenodes.h:140
bool hasRecursive
Definition: parsenodes.h:130
List * rtable
Definition: parsenodes.h:137
bool recursive
Definition: parsenodes.h:1400
List * returningList
Definition: parsenodes.h:146
bool p_hasModifyingCTE
Definition: parse_node.h:210
bool inh
Definition: primnodes.h:69
#define ACL_UPDATE
Definition: parsenodes.h:76
void transformFromClause(ParseState *pstate, List *frmList)
Definition: parse_clause.c:114
int setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource, AclMode requiredPerms)
Definition: parse_clause.c:178
CmdType commandType
Definition: parsenodes.h:112
bool hasTargetSRFs
Definition: parsenodes.h:127
#define makeNode(_type_)
Definition: nodes.h:576
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
RangeVar * relation
Definition: parsenodes.h:1559
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:105
List * returningList
Definition: parsenodes.h:1563
List * cteList
Definition: parsenodes.h:135
bool hasSubLinks
Definition: parsenodes.h:128
void assign_query_collations(ParseState *pstate, Query *query)
bool p_is_insert
Definition: parse_node.h:192
List * p_joinlist
Definition: parse_node.h:182
bool hasModifyingCTE
Definition: parsenodes.h:131
WithClause * withClause
Definition: parsenodes.h:1564
List * p_rtable
Definition: parse_node.h:180

◆ transformUpdateTargetList()

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

Definition at line 2293 of file analyze.c.

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

Referenced by transformOnConflictClause(), and transformUpdateStmt().

2294 {
2295  List *tlist = NIL;
2296  RangeTblEntry *target_rte;
2297  ListCell *orig_tl;
2298  ListCell *tl;
2299  TupleDesc tupdesc = pstate->p_target_relation->rd_att;
2300 
2301  tlist = transformTargetList(pstate, origTlist,
2303 
2304  /* Prepare to assign non-conflicting resnos to resjunk attributes */
2307 
2308  /* Prepare non-junk columns for assignment to target table */
2309  target_rte = pstate->p_target_nsitem->p_rte;
2310  orig_tl = list_head(origTlist);
2311 
2312  foreach(tl, tlist)
2313  {
2314  TargetEntry *tle = (TargetEntry *) lfirst(tl);
2315  ResTarget *origTarget;
2316  int attrno;
2317 
2318  if (tle->resjunk)
2319  {
2320  /*
2321  * Resjunk nodes need no additional processing, but be sure they
2322  * have resnos that do not match any target columns; else rewriter
2323  * or planner might get confused. They don't need a resname
2324  * either.
2325  */
2326  tle->resno = (AttrNumber) pstate->p_next_resno++;
2327  tle->resname = NULL;
2328  continue;
2329  }
2330  if (orig_tl == NULL)
2331  elog(ERROR, "UPDATE target count mismatch --- internal error");
2332  origTarget = lfirst_node(ResTarget, orig_tl);
2333 
2334  attrno = attnameAttNum(pstate->p_target_relation,
2335  origTarget->name, true);
2336  if (attrno == InvalidAttrNumber)
2337  ereport(ERROR,
2338  (errcode(ERRCODE_UNDEFINED_COLUMN),
2339  errmsg("column \"%s\" of relation \"%s\" does not exist",
2340  origTarget->name,
2342  parser_errposition(pstate, origTarget->location)));
2343 
2344  updateTargetListEntry(pstate, tle, origTarget->name,
2345  attrno,
2346  origTarget->indirection,
2347  origTarget->location);
2348 
2349  /* Mark the target column as requiring update permissions */
2350  target_rte->updatedCols = bms_add_member(target_rte->updatedCols,
2352 
2353  orig_tl = lnext(origTlist, orig_tl);
2354  }
2355  if (orig_tl != NULL)
2356  elog(ERROR, "UPDATE target count mismatch --- internal error");
2357 
2358  fill_extraUpdatedCols(target_rte, tupdesc);
2359 
2360  return tlist;
2361 }
List * indirection
Definition: parsenodes.h:443
#define NIL
Definition: pg_list.h:65
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:310
char * name
Definition: parsenodes.h:442
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:462
int errcode(int sqlerrcode)
Definition: elog.c:610
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
ParseNamespaceItem * p_target_nsitem
Definition: parse_node.h:191
char * resname
Definition: primnodes.h:1412
int location
Definition: parsenodes.h:445
List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind)
Definition: parse_target.c:133
RangeTblEntry * p_rte
Definition: parse_node.h:257
bool resjunk
Definition: primnodes.h:1417
#define ERROR
Definition: elog.h:43
void fill_extraUpdatedCols(RangeTblEntry *target_rte, TupleDesc tupdesc)
Definition: analyze.c:2368
#define lfirst_node(type, lc)
Definition: pg_list.h:172
AttrNumber resno
Definition: primnodes.h:1411
int p_next_resno
Definition: parse_node.h:195
#define RelationGetRelationName(relation)
Definition: rel.h:490
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
TupleDesc rd_att
Definition: rel.h:110
#define ereport(elevel,...)
Definition: elog.h:144
Bitmapset * updatedCols
Definition: parsenodes.h:1124
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
#define lfirst(lc)
Definition: pg_list.h:169
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
#define InvalidAttrNumber
Definition: attnum.h:23
int errmsg(const char *fmt,...)
Definition: elog.c:821
Relation p_target_relation
Definition: parse_node.h:190
#define elog(elevel,...)
Definition: elog.h:214
Definition: pg_list.h:50
void updateTargetListEntry(ParseState *pstate, TargetEntry *tle, char *colname, int attrno, List *indirection, int location)
Definition: parse_target.c:616
int16 AttrNumber
Definition: attnum.h:21

◆ transformValuesClause()

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

Definition at line 1331 of file analyze.c.

References addNSItemToQuery(), addRangeTableEntryForValues(), Assert, assign_query_collations(), CMD_SELECT, coerce_to_common_type(), Query::commandType, contain_vars_of_level(), Query::cteList, SelectStmt::distinctClause, ereport, errcode(), errmsg(), ERROR, expandNSItemAttrs(), 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, Query::limitOption, SelectStmt::limitOption, 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, 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().

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

Variable Documentation

◆ post_parse_analyze_hook

post_parse_analyze_hook_type post_parse_analyze_hook = NULL