PostgreSQL Source Code  git master
analyze.c File Reference
#include "postgres.h"
#include "access/sysattr.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "nodes/queryjumble.h"
#include "optimizer/optimizer.h"
#include "parser/analyze.h"
#include "parser/parse_agg.h"
#include "parser/parse_clause.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_cte.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_merge.h"
#include "parser/parse_oper.h"
#include "parser/parse_param.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
#include "parser/parse_type.h"
#include "parser/parsetree.h"
#include "utils/backend_status.h"
#include "utils/builtins.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for analyze.c:

Go to the source code of this file.

Functions

static QuerytransformOptionalSelectInto (ParseState *pstate, Node *parseTree)
 
static QuerytransformDeleteStmt (ParseState *pstate, DeleteStmt *stmt)
 
static QuerytransformInsertStmt (ParseState *pstate, InsertStmt *stmt)
 
static 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 QuerytransformReturnStmt (ParseState *pstate, ReturnStmt *stmt)
 
static QuerytransformUpdateStmt (ParseState *pstate, UpdateStmt *stmt)
 
static QuerytransformPLAssignStmt (ParseState *pstate, PLAssignStmt *stmt)
 
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_fixedparams (RawStmt *parseTree, const char *sourceText, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
 
Queryparse_analyze_varparams (RawStmt *parseTree, const char *sourceText, Oid **paramTypes, int *numParams, QueryEnvironment *queryEnv)
 
Queryparse_analyze_withcb (RawStmt *parseTree, const char *sourceText, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
 
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 stmt_requires_parse_analysis (RawStmt *parseTree)
 
bool analyze_requires_snapshot (RawStmt *parseTree)
 
ListtransformInsertRow (ParseState *pstate, List *exprlist, List *stmtcols, List *icolumns, List *attrnos, bool strip_indirection)
 
ListBuildOnConflictExcludedTargetlist (Relation targetrel, Index exclRelIndex)
 
SortGroupClausemakeSortGroupClauseForSetOp (Oid rescoltype, bool require_hash)
 
ListtransformUpdateTargetList (ParseState *pstate, List *origTlist)
 
ListtransformReturningList (ParseState *pstate, List *returningList, ParseExprKind exprKind)
 
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 485 of file analyze.c.

486 {
487  /*
488  * Currently, this should return true in exactly the same cases that
489  * stmt_requires_parse_analysis() does, so we just invoke that function
490  * rather than duplicating it. We keep the two entry points separate for
491  * clarity of callers, since from the callers' standpoint these are
492  * different conditions.
493  *
494  * While there may someday be a statement type for which transformStmt()
495  * does something nontrivial and yet no snapshot is needed for that
496  * processing, it seems likely that making such a choice would be fragile.
497  * If you want to install an exception, document the reasoning for it in a
498  * comment.
499  */
500  return stmt_requires_parse_analysis(parseTree);
501 }
bool stmt_requires_parse_analysis(RawStmt *parseTree)
Definition: analyze.c:441

References stmt_requires_parse_analysis().

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

◆ applyLockingClause()

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

Definition at line 3529 of file analyze.c.

3532 {
3533  RowMarkClause *rc;
3534 
3535  Assert(strength != LCS_NONE); /* else caller error */
3536 
3537  /* If it's an explicit clause, make sure hasForUpdate gets set */
3538  if (!pushedDown)
3539  qry->hasForUpdate = true;
3540 
3541  /* Check for pre-existing entry for same rtindex */
3542  if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
3543  {
3544  /*
3545  * If the same RTE is specified with more than one locking strength,
3546  * use the strongest. (Reasonable, since you can't take both a shared
3547  * and exclusive lock at the same time; it'll end up being exclusive
3548  * anyway.)
3549  *
3550  * Similarly, if the same RTE is specified with more than one lock
3551  * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
3552  * turn wins over waiting for the lock (the default). This is a bit
3553  * more debatable but raising an error doesn't seem helpful. (Consider
3554  * for instance SELECT FOR UPDATE NOWAIT from a view that internally
3555  * contains a plain FOR UPDATE spec.) Having NOWAIT win over SKIP
3556  * LOCKED is reasonable since the former throws an error in case of
3557  * coming across a locked tuple, which may be undesirable in some
3558  * cases but it seems better than silently returning inconsistent
3559  * results.
3560  *
3561  * And of course pushedDown becomes false if any clause is explicit.
3562  */
3563  rc->strength = Max(rc->strength, strength);
3564  rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
3565  rc->pushedDown &= pushedDown;
3566  return;
3567  }
3568 
3569  /* Make a new RowMarkClause */
3570  rc = makeNode(RowMarkClause);
3571  rc->rti = rtindex;
3572  rc->strength = strength;
3573  rc->waitPolicy = waitPolicy;
3574  rc->pushedDown = pushedDown;
3575  qry->rowMarks = lappend(qry->rowMarks, rc);
3576 }
#define Max(x, y)
Definition: c.h:998
#define Assert(condition)
Definition: c.h:858
List * lappend(List *list, void *datum)
Definition: list.c:339
@ LCS_NONE
Definition: lockoptions.h:23
#define makeNode(_type_)
Definition: nodes.h:155
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
List * rowMarks
Definition: parsenodes.h:217
LockClauseStrength strength
Definition: parsenodes.h:1583
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1584

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

Referenced by markQueryForLocking(), and transformLockingClause().

◆ BuildOnConflictExcludedTargetlist()

List* BuildOnConflictExcludedTargetlist ( Relation  targetrel,
Index  exclRelIndex 
)

Definition at line 1225 of file analyze.c.

1227 {
1228  List *result = NIL;
1229  int attno;
1230  Var *var;
1231  TargetEntry *te;
1232 
1233  /*
1234  * Note that resnos of the tlist must correspond to attnos of the
1235  * underlying relation, hence we need entries for dropped columns too.
1236  */
1237  for (attno = 0; attno < RelationGetNumberOfAttributes(targetrel); attno++)
1238  {
1239  Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno);
1240  char *name;
1241 
1242  if (attr->attisdropped)
1243  {
1244  /*
1245  * can't use atttypid here, but it doesn't really matter what type
1246  * the Const claims to be.
1247  */
1248  var = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
1249  name = NULL;
1250  }
1251  else
1252  {
1253  var = makeVar(exclRelIndex, attno + 1,
1254  attr->atttypid, attr->atttypmod,
1255  attr->attcollation,
1256  0);
1257  name = pstrdup(NameStr(attr->attname));
1258  }
1259 
1260  te = makeTargetEntry((Expr *) var,
1261  attno + 1,
1262  name,
1263  false);
1264 
1265  result = lappend(result, te);
1266  }
1267 
1268  /*
1269  * Add a whole-row-Var entry to support references to "EXCLUDED.*". Like
1270  * the other entries in the EXCLUDED tlist, its resno must match the Var's
1271  * varattno, else the wrong things happen while resolving references in
1272  * setrefs.c. This is against normal conventions for targetlists, but
1273  * it's okay since we don't use this as a real tlist.
1274  */
1275  var = makeVar(exclRelIndex, InvalidAttrNumber,
1276  targetrel->rd_rel->reltype,
1277  -1, InvalidOid, 0);
1278  te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
1279  result = lappend(result, te);
1280 
1281  return result;
1282 }
#define InvalidAttrNumber
Definition: attnum.h:23
#define NameStr(name)
Definition: c.h:746
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:240
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:339
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
char * pstrdup(const char *in)
Definition: mcxt.c:1695
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define NIL
Definition: pg_list.h:68
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:511
Definition: pg_list.h:54
TupleDesc rd_att
Definition: rel.h:112
Form_pg_class rd_rel
Definition: rel.h:111
Definition: primnodes.h:248
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
const char * name

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

◆ CheckSelectLocking()

void CheckSelectLocking ( Query qry,
LockClauseStrength  strength 
)

Definition at line 3238 of file analyze.c.

3239 {
3240  Assert(strength != LCS_NONE); /* else caller error */
3241 
3242  if (qry->setOperations)
3243  ereport(ERROR,
3244  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3245  /*------
3246  translator: %s is a SQL row locking clause such as FOR UPDATE */
3247  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
3248  LCS_asString(strength))));
3249  if (qry->distinctClause != NIL)
3250  ereport(ERROR,
3251  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3252  /*------
3253  translator: %s is a SQL row locking clause such as FOR UPDATE */
3254  errmsg("%s is not allowed with DISTINCT clause",
3255  LCS_asString(strength))));
3256  if (qry->groupClause != NIL || qry->groupingSets != NIL)
3257  ereport(ERROR,
3258  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3259  /*------
3260  translator: %s is a SQL row locking clause such as FOR UPDATE */
3261  errmsg("%s is not allowed with GROUP BY clause",
3262  LCS_asString(strength))));
3263  if (qry->havingQual != NULL)
3264  ereport(ERROR,
3265  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3266  /*------
3267  translator: %s is a SQL row locking clause such as FOR UPDATE */
3268  errmsg("%s is not allowed with HAVING clause",
3269  LCS_asString(strength))));
3270  if (qry->hasAggs)
3271  ereport(ERROR,
3272  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3273  /*------
3274  translator: %s is a SQL row locking clause such as FOR UPDATE */
3275  errmsg("%s is not allowed with aggregate functions",
3276  LCS_asString(strength))));
3277  if (qry->hasWindowFuncs)
3278  ereport(ERROR,
3279  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3280  /*------
3281  translator: %s is a SQL row locking clause such as FOR UPDATE */
3282  errmsg("%s is not allowed with window functions",
3283  LCS_asString(strength))));
3284  if (qry->hasTargetSRFs)
3285  ereport(ERROR,
3286  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3287  /*------
3288  translator: %s is a SQL row locking clause such as FOR UPDATE */
3289  errmsg("%s is not allowed with set-returning functions in the target list",
3290  LCS_asString(strength))));
3291 }
int errcode(int sqlerrcode)
Definition: elog.c:857
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:3213
Node * setOperations
Definition: parsenodes.h:219
List * groupClause
Definition: parsenodes.h:200
Node * havingQual
Definition: parsenodes.h:205
List * groupingSets
Definition: parsenodes.h:203
List * distinctClause
Definition: parsenodes.h:209

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

Referenced by preprocess_rowmarks(), and transformLockingClause().

◆ count_rowexpr_columns()

static int count_rowexpr_columns ( ParseState pstate,
Node expr 
)
static

Definition at line 1295 of file analyze.c.

1296 {
1297  if (expr == NULL)
1298  return -1;
1299  if (IsA(expr, RowExpr))
1300  return list_length(((RowExpr *) expr)->args);
1301  if (IsA(expr, Var))
1302  {
1303  Var *var = (Var *) expr;
1304  AttrNumber attnum = var->varattno;
1305 
1306  if (attnum > 0 && var->vartype == RECORDOID)
1307  {
1308  RangeTblEntry *rte;
1309 
1310  rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup);
1311  if (rte->rtekind == RTE_SUBQUERY)
1312  {
1313  /* Subselect-in-FROM: examine sub-select's output expr */
1315  attnum);
1316 
1317  if (ste == NULL || ste->resjunk)
1318  return -1;
1319  expr = (Node *) ste->expr;
1320  if (IsA(expr, RowExpr))
1321  return list_length(((RowExpr *) expr)->args);
1322  }
1323  }
1324  }
1325  return -1;
1326 }
int16 AttrNumber
Definition: attnum.h:21
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
@ RTE_SUBQUERY
Definition: parsenodes.h:1029
int16 attnum
Definition: pg_attribute.h:74
static int list_length(const List *l)
Definition: pg_list.h:152
Definition: nodes.h:129
List * targetList
Definition: parsenodes.h:191
Query * subquery
Definition: parsenodes.h:1114
RTEKind rtekind
Definition: parsenodes.h:1057
Expr * expr
Definition: primnodes.h:2192
AttrNumber varattno
Definition: primnodes.h:260
int varno
Definition: primnodes.h:255
Index varlevelsup
Definition: primnodes.h:280

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

Referenced by transformInsertRow().

◆ determineRecursiveColTypes()

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

Definition at line 2334 of file analyze.c.

2335 {
2336  Node *node;
2337  int leftmostRTI;
2338  Query *leftmostQuery;
2339  List *targetList;
2340  ListCell *left_tlist;
2341  ListCell *nrtl;
2342  int next_resno;
2343 
2344  /*
2345  * Find leftmost leaf SELECT
2346  */
2347  node = larg;
2348  while (node && IsA(node, SetOperationStmt))
2349  node = ((SetOperationStmt *) node)->larg;
2350  Assert(node && IsA(node, RangeTblRef));
2351  leftmostRTI = ((RangeTblRef *) node)->rtindex;
2352  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2353  Assert(leftmostQuery != NULL);
2354 
2355  /*
2356  * Generate dummy targetlist using column names of leftmost select and
2357  * dummy result expressions of the non-recursive term.
2358  */
2359  targetList = NIL;
2360  next_resno = 1;
2361 
2362  forboth(nrtl, nrtargetlist, left_tlist, leftmostQuery->targetList)
2363  {
2364  TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
2365  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
2366  char *colName;
2367  TargetEntry *tle;
2368 
2369  Assert(!lefttle->resjunk);
2370  colName = pstrdup(lefttle->resname);
2371  tle = makeTargetEntry(nrtle->expr,
2372  next_resno++,
2373  colName,
2374  false);
2375  targetList = lappend(targetList, tle);
2376  }
2377 
2378  /* Now build CTE's output column info using dummy targetlist */
2379  analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
2380 }
void analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
Definition: parse_cte.c:570
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define lfirst(lc)
Definition: pg_list.h:172
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
CommonTableExpr * p_parent_cte
Definition: parse_node.h:206
List * p_rtable
Definition: parse_node.h:194

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

Referenced by transformSetOperationTree().

◆ LCS_asString()

const char* LCS_asString ( LockClauseStrength  strength)

Definition at line 3213 of file analyze.c.

3214 {
3215  switch (strength)
3216  {
3217  case LCS_NONE:
3218  Assert(false);
3219  break;
3220  case LCS_FORKEYSHARE:
3221  return "FOR KEY SHARE";
3222  case LCS_FORSHARE:
3223  return "FOR SHARE";
3224  case LCS_FORNOKEYUPDATE:
3225  return "FOR NO KEY UPDATE";
3226  case LCS_FORUPDATE:
3227  return "FOR UPDATE";
3228  }
3229  return "FOR some"; /* shouldn't happen */
3230 }
@ LCS_FORUPDATE
Definition: lockoptions.h:27
@ LCS_FORSHARE
Definition: lockoptions.h:25
@ LCS_FORKEYSHARE
Definition: lockoptions.h:24
@ LCS_FORNOKEYUPDATE
Definition: lockoptions.h:26

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

◆ makeSortGroupClauseForSetOp()

SortGroupClause* makeSortGroupClauseForSetOp ( Oid  rescoltype,
bool  require_hash 
)

Definition at line 1956 of file analyze.c.

1957 {
1959  Oid sortop;
1960  Oid eqop;
1961  bool hashable;
1962 
1963  /* determine the eqop and optional sortop */
1964  get_sort_group_operators(rescoltype,
1965  false, true, false,
1966  &sortop, &eqop, NULL,
1967  &hashable);
1968 
1969  /*
1970  * The type cache doesn't believe that record is hashable (see
1971  * cache_record_field_properties()), but if the caller really needs hash
1972  * support, we can assume it does. Worst case, if any components of the
1973  * record don't support hashing, we will fail at execution.
1974  */
1975  if (require_hash && (rescoltype == RECORDOID || rescoltype == RECORDARRAYOID))
1976  hashable = true;
1977 
1978  /* we don't have a tlist yet, so can't assign sortgrouprefs */
1979  grpcl->tleSortGroupRef = 0;
1980  grpcl->eqop = eqop;
1981  grpcl->sortop = sortop;
1982  grpcl->nulls_first = false; /* OK with or without sortop */
1983  grpcl->hashable = hashable;
1984 
1985  return grpcl;
1986 }
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:180
unsigned int Oid
Definition: postgres_ext.h:31
Index tleSortGroupRef
Definition: parsenodes.h:1442

References SortGroupClause::eqop, get_sort_group_operators(), makeNode, SortGroupClause::nulls_first, SortGroupClause::sortop, and SortGroupClause::tleSortGroupRef.

Referenced by rewriteSearchAndCycle(), and transformSetOperationTree().

◆ parse_analyze_fixedparams()

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

Definition at line 104 of file analyze.c.

107 {
108  ParseState *pstate = make_parsestate(NULL);
109  Query *query;
110  JumbleState *jstate = NULL;
111 
112  Assert(sourceText != NULL); /* required as of 8.4 */
113 
114  pstate->p_sourcetext = sourceText;
115 
116  if (numParams > 0)
117  setup_parse_fixed_parameters(pstate, paramTypes, numParams);
118 
119  pstate->p_queryEnv = queryEnv;
120 
121  query = transformTopLevelStmt(pstate, parseTree);
122 
123  if (IsQueryIdEnabled())
124  jstate = JumbleQuery(query);
125 
127  (*post_parse_analyze_hook) (pstate, query, jstate);
128 
129  free_parsestate(pstate);
130 
131  pgstat_report_query_id(query->queryId, false);
132 
133  return query;
134 }
void pgstat_report_query_id(uint64 query_id, bool force)
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:72
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:39
void setup_parse_fixed_parameters(ParseState *pstate, const Oid *paramTypes, int numParams)
Definition: parse_param.c:67
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:248
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:58
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:77
JumbleState * JumbleQuery(Query *query)
QueryEnvironment * p_queryEnv
Definition: parse_node.h:220
const char * p_sourcetext
Definition: parse_node.h:193

References Assert, free_parsestate(), IsQueryIdEnabled(), JumbleQuery(), make_parsestate(), ParseState::p_queryEnv, ParseState::p_sourcetext, pgstat_report_query_id(), post_parse_analyze_hook, setup_parse_fixed_parameters(), and transformTopLevelStmt().

Referenced by DefineView(), and pg_analyze_and_rewrite_fixedparams().

◆ parse_analyze_varparams()

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

Definition at line 144 of file analyze.c.

147 {
148  ParseState *pstate = make_parsestate(NULL);
149  Query *query;
150  JumbleState *jstate = NULL;
151 
152  Assert(sourceText != NULL); /* required as of 8.4 */
153 
154  pstate->p_sourcetext = sourceText;
155 
156  setup_parse_variable_parameters(pstate, paramTypes, numParams);
157 
158  pstate->p_queryEnv = queryEnv;
159 
160  query = transformTopLevelStmt(pstate, parseTree);
161 
162  /* make sure all is well with parameter types */
163  check_variable_parameters(pstate, query);
164 
165  if (IsQueryIdEnabled())
166  jstate = JumbleQuery(query);
167 
169  (*post_parse_analyze_hook) (pstate, query, jstate);
170 
171  free_parsestate(pstate);
172 
173  pgstat_report_query_id(query->queryId, false);
174 
175  return query;
176 }
void check_variable_parameters(ParseState *pstate, Query *query)
Definition: parse_param.c:268
void setup_parse_variable_parameters(ParseState *pstate, Oid **paramTypes, int *numParams)
Definition: parse_param.c:83

References Assert, check_variable_parameters(), free_parsestate(), IsQueryIdEnabled(), JumbleQuery(), make_parsestate(), ParseState::p_queryEnv, ParseState::p_sourcetext, pgstat_report_query_id(), post_parse_analyze_hook, setup_parse_variable_parameters(), and transformTopLevelStmt().

Referenced by pg_analyze_and_rewrite_varparams().

◆ parse_analyze_withcb()

Query* parse_analyze_withcb ( RawStmt parseTree,
const char *  sourceText,
ParserSetupHook  parserSetup,
void *  parserSetupArg,
QueryEnvironment queryEnv 
)

Definition at line 185 of file analyze.c.

189 {
190  ParseState *pstate = make_parsestate(NULL);
191  Query *query;
192  JumbleState *jstate = NULL;
193 
194  Assert(sourceText != NULL); /* required as of 8.4 */
195 
196  pstate->p_sourcetext = sourceText;
197  pstate->p_queryEnv = queryEnv;
198  (*parserSetup) (pstate, parserSetupArg);
199 
200  query = transformTopLevelStmt(pstate, parseTree);
201 
202  if (IsQueryIdEnabled())
203  jstate = JumbleQuery(query);
204 
206  (*post_parse_analyze_hook) (pstate, query, jstate);
207 
208  free_parsestate(pstate);
209 
210  pgstat_report_query_id(query->queryId, false);
211 
212  return query;
213 }

References Assert, free_parsestate(), IsQueryIdEnabled(), JumbleQuery(), make_parsestate(), ParseState::p_queryEnv, ParseState::p_sourcetext, pgstat_report_query_id(), post_parse_analyze_hook, and transformTopLevelStmt().

Referenced by pg_analyze_and_rewrite_withcb().

◆ parse_sub_analyze()

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

Definition at line 221 of file analyze.c.

225 {
226  ParseState *pstate = make_parsestate(parentParseState);
227  Query *query;
228 
229  pstate->p_parent_cte = parentCTE;
230  pstate->p_locked_from_parent = locked_from_parent;
231  pstate->p_resolve_unknowns = resolve_unknowns;
232 
233  query = transformStmt(pstate, parseTree);
234 
235  free_parsestate(pstate);
236 
237  return query;
238 }
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:311
bool p_locked_from_parent
Definition: parse_node.h:215
bool p_resolve_unknowns
Definition: parse_node.h:217

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

◆ stmt_requires_parse_analysis()

bool stmt_requires_parse_analysis ( RawStmt parseTree)

Definition at line 441 of file analyze.c.

442 {
443  bool result;
444 
445  switch (nodeTag(parseTree->stmt))
446  {
447  /*
448  * Optimizable statements
449  */
450  case T_InsertStmt:
451  case T_DeleteStmt:
452  case T_UpdateStmt:
453  case T_MergeStmt:
454  case T_SelectStmt:
455  case T_ReturnStmt:
456  case T_PLAssignStmt:
457  result = true;
458  break;
459 
460  /*
461  * Special cases
462  */
463  case T_DeclareCursorStmt:
464  case T_ExplainStmt:
465  case T_CreateTableAsStmt:
466  case T_CallStmt:
467  result = true;
468  break;
469 
470  default:
471  /* all other statements just get wrapped in a CMD_UTILITY Query */
472  result = false;
473  break;
474  }
475 
476  return result;
477 }
#define nodeTag(nodeptr)
Definition: nodes.h:133
Node * stmt
Definition: parsenodes.h:2025

References nodeTag, and RawStmt::stmt.

Referenced by analyze_requires_snapshot().

◆ transformCallStmt()

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

Definition at line 3088 of file analyze.c.

3089 {
3090  List *targs;
3091  ListCell *lc;
3092  Node *node;
3093  FuncExpr *fexpr;
3094  HeapTuple proctup;
3095  Datum proargmodes;
3096  bool isNull;
3097  List *outargs = NIL;
3098  Query *result;
3099 
3100  /*
3101  * First, do standard parse analysis on the procedure call and its
3102  * arguments, allowing us to identify the called procedure.
3103  */
3104  targs = NIL;
3105  foreach(lc, stmt->funccall->args)
3106  {
3107  targs = lappend(targs, transformExpr(pstate,
3108  (Node *) lfirst(lc),
3110  }
3111 
3112  node = ParseFuncOrColumn(pstate,
3113  stmt->funccall->funcname,
3114  targs,
3115  pstate->p_last_srf,
3116  stmt->funccall,
3117  true,
3118  stmt->funccall->location);
3119 
3120  assign_expr_collations(pstate, node);
3121 
3122  fexpr = castNode(FuncExpr, node);
3123 
3124  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
3125  if (!HeapTupleIsValid(proctup))
3126  elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
3127 
3128  /*
3129  * Expand the argument list to deal with named-argument notation and
3130  * default arguments. For ordinary FuncExprs this'd be done during
3131  * planning, but a CallStmt doesn't go through planning, and there seems
3132  * no good reason not to do it here.
3133  */
3134  fexpr->args = expand_function_arguments(fexpr->args,
3135  true,
3136  fexpr->funcresulttype,
3137  proctup);
3138 
3139  /* Fetch proargmodes; if it's null, there are no output args */
3140  proargmodes = SysCacheGetAttr(PROCOID, proctup,
3141  Anum_pg_proc_proargmodes,
3142  &isNull);
3143  if (!isNull)
3144  {
3145  /*
3146  * Split the list into input arguments in fexpr->args and output
3147  * arguments in stmt->outargs. INOUT arguments appear in both lists.
3148  */
3149  ArrayType *arr;
3150  int numargs;
3151  char *argmodes;
3152  List *inargs;
3153  int i;
3154 
3155  arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
3156  numargs = list_length(fexpr->args);
3157  if (ARR_NDIM(arr) != 1 ||
3158  ARR_DIMS(arr)[0] != numargs ||
3159  ARR_HASNULL(arr) ||
3160  ARR_ELEMTYPE(arr) != CHAROID)
3161  elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
3162  numargs);
3163  argmodes = (char *) ARR_DATA_PTR(arr);
3164 
3165  inargs = NIL;
3166  i = 0;
3167  foreach(lc, fexpr->args)
3168  {
3169  Node *n = lfirst(lc);
3170 
3171  switch (argmodes[i])
3172  {
3173  case PROARGMODE_IN:
3174  case PROARGMODE_VARIADIC:
3175  inargs = lappend(inargs, n);
3176  break;
3177  case PROARGMODE_OUT:
3178  outargs = lappend(outargs, n);
3179  break;
3180  case PROARGMODE_INOUT:
3181  inargs = lappend(inargs, n);
3182  outargs = lappend(outargs, copyObject(n));
3183  break;
3184  default:
3185  /* note we don't support PROARGMODE_TABLE */
3186  elog(ERROR, "invalid argmode %c for procedure",
3187  argmodes[i]);
3188  break;
3189  }
3190  i++;
3191  }
3192  fexpr->args = inargs;
3193  }
3194 
3195  stmt->funcexpr = fexpr;
3196  stmt->outargs = outargs;
3197 
3198  ReleaseSysCache(proctup);
3199 
3200  /* represent the command as a utility Query */
3201  result = makeNode(Query);
3202  result->commandType = CMD_UTILITY;
3203  result->utilityStmt = (Node *) stmt;
3204 
3205  return result;
3206 }
#define ARR_NDIM(a)
Definition: array.h:290
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
#define ARR_DIMS(a)
Definition: array.h:294
#define ARR_HASNULL(a)
Definition: array.h:291
List * expand_function_arguments(List *args, bool include_out_arguments, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:4163
#define elog(elevel,...)
Definition: elog.h:224
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define stmt
Definition: indent_codes.h:59
int i
Definition: isn.c:73
#define copyObject(obj)
Definition: nodes.h:224
@ CMD_UTILITY
Definition: nodes.h:270
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:121
Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *last_srf, FuncCall *fn, bool proc_call, int location)
Definition: parse_func.c:90
@ EXPR_KIND_CALL_ARGUMENT
Definition: parse_node.h:81
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
Oid funcid
Definition: primnodes.h:750
List * args
Definition: primnodes.h:768
Node * p_last_srf
Definition: parse_node.h:229
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:136
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:479

References FuncExpr::args, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, assign_expr_collations(), castNode, CMD_UTILITY, Query::commandType, copyObject, DatumGetArrayTypeP, elog, ERROR, expand_function_arguments(), EXPR_KIND_CALL_ARGUMENT, FuncExpr::funcid, HeapTupleIsValid, i, lappend(), lfirst, list_length(), makeNode, NIL, ObjectIdGetDatum(), ParseState::p_last_srf, ParseFuncOrColumn(), ReleaseSysCache(), SearchSysCache1(), stmt, SysCacheGetAttr(), transformExpr(), and Query::utilityStmt.

Referenced by transformStmt().

◆ transformCreateTableAsStmt()

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

Definition at line 3013 of file analyze.c.

3014 {
3015  Query *result;
3016  Query *query;
3017 
3018  /* transform contained query, not allowing SELECT INTO */
3019  query = transformStmt(pstate, stmt->query);
3020  stmt->query = (Node *) query;
3021 
3022  /* additional work needed for CREATE MATERIALIZED VIEW */
3023  if (stmt->objtype == OBJECT_MATVIEW)
3024  {
3025  /*
3026  * Prohibit a data-modifying CTE in the query used to create a
3027  * materialized view. It's not sufficiently clear what the user would
3028  * want to happen if the MV is refreshed or incrementally maintained.
3029  */
3030  if (query->hasModifyingCTE)
3031  ereport(ERROR,
3032  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3033  errmsg("materialized views must not use data-modifying statements in WITH")));
3034 
3035  /*
3036  * Check whether any temporary database objects are used in the
3037  * creation query. It would be hard to refresh data or incrementally
3038  * maintain it if a source disappeared.
3039  */
3040  if (isQueryUsingTempRelation(query))
3041  ereport(ERROR,
3042  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3043  errmsg("materialized views must not use temporary tables or views")));
3044 
3045  /*
3046  * A materialized view would either need to save parameters for use in
3047  * maintaining/loading the data or prohibit them entirely. The latter
3048  * seems safer and more sane.
3049  */
3050  if (query_contains_extern_params(query))
3051  ereport(ERROR,
3052  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3053  errmsg("materialized views may not be defined using bound parameters")));
3054 
3055  /*
3056  * For now, we disallow unlogged materialized views, because it seems
3057  * like a bad idea for them to just go to empty after a crash. (If we
3058  * could mark them as unpopulated, that would be better, but that
3059  * requires catalog changes which crash recovery can't presently
3060  * handle.)
3061  */
3062  if (stmt->into->rel->relpersistence == RELPERSISTENCE_UNLOGGED)
3063  ereport(ERROR,
3064  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3065  errmsg("materialized views cannot be unlogged")));
3066 
3067  /*
3068  * At runtime, we'll need a copy of the parsed-but-not-rewritten Query
3069  * for purposes of creating the view's ON SELECT rule. We stash that
3070  * in the IntoClause because that's where intorel_startup() can
3071  * conveniently get it from.
3072  */
3073  stmt->into->viewQuery = (Node *) copyObject(query);
3074  }
3075 
3076  /* represent the command as a utility Query */
3077  result = makeNode(Query);
3078  result->commandType = CMD_UTILITY;
3079  result->utilityStmt = (Node *) stmt;
3080 
3081  return result;
3082 }
bool query_contains_extern_params(Query *query)
Definition: parse_param.c:330
bool isQueryUsingTempRelation(Query *query)
@ OBJECT_MATVIEW
Definition: parsenodes.h:2284

References CMD_UTILITY, Query::commandType, copyObject, ereport, errcode(), errmsg(), ERROR, isQueryUsingTempRelation(), makeNode, OBJECT_MATVIEW, query_contains_extern_params(), stmt, transformStmt(), and Query::utilityStmt.

Referenced by transformStmt().

◆ transformDeclareCursorStmt()

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

Definition at line 2868 of file analyze.c.

2869 {
2870  Query *result;
2871  Query *query;
2872 
2873  if ((stmt->options & CURSOR_OPT_SCROLL) &&
2874  (stmt->options & CURSOR_OPT_NO_SCROLL))
2875  ereport(ERROR,
2876  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2877  /* translator: %s is a SQL keyword */
2878  errmsg("cannot specify both %s and %s",
2879  "SCROLL", "NO SCROLL")));
2880 
2881  if ((stmt->options & CURSOR_OPT_ASENSITIVE) &&
2882  (stmt->options & CURSOR_OPT_INSENSITIVE))
2883  ereport(ERROR,
2884  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2885  /* translator: %s is a SQL keyword */
2886  errmsg("cannot specify both %s and %s",
2887  "ASENSITIVE", "INSENSITIVE")));
2888 
2889  /* Transform contained query, not allowing SELECT INTO */
2890  query = transformStmt(pstate, stmt->query);
2891  stmt->query = (Node *) query;
2892 
2893  /* Grammar should not have allowed anything but SELECT */
2894  if (!IsA(query, Query) ||
2895  query->commandType != CMD_SELECT)
2896  elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR");
2897 
2898  /*
2899  * We also disallow data-modifying WITH in a cursor. (This could be
2900  * allowed, but the semantics of when the updates occur might be
2901  * surprising.)
2902  */
2903  if (query->hasModifyingCTE)
2904  ereport(ERROR,
2905  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2906  errmsg("DECLARE CURSOR must not contain data-modifying statements in WITH")));
2907 
2908  /* FOR UPDATE and WITH HOLD are not compatible */
2909  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
2910  ereport(ERROR,
2911  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2912  /*------
2913  translator: %s is a SQL row locking clause such as FOR UPDATE */
2914  errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
2916  linitial(query->rowMarks))->strength)),
2917  errdetail("Holdable cursors must be READ ONLY.")));
2918 
2919  /* FOR UPDATE and SCROLL are not compatible */
2920  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
2921  ereport(ERROR,
2922  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2923  /*------
2924  translator: %s is a SQL row locking clause such as FOR UPDATE */
2925  errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
2927  linitial(query->rowMarks))->strength)),
2928  errdetail("Scrollable cursors must be READ ONLY.")));
2929 
2930  /* FOR UPDATE and INSENSITIVE are not compatible */
2931  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
2932  ereport(ERROR,
2933  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2934  /*------
2935  translator: %s is a SQL row locking clause such as FOR UPDATE */
2936  errmsg("DECLARE INSENSITIVE CURSOR ... %s is not valid",
2938  linitial(query->rowMarks))->strength)),
2939  errdetail("Insensitive cursors must be READ ONLY.")));
2940 
2941  /* represent the command as a utility Query */
2942  result = makeNode(Query);
2943  result->commandType = CMD_UTILITY;
2944  result->utilityStmt = (Node *) stmt;
2945 
2946  return result;
2947 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
@ CMD_SELECT
Definition: nodes.h:265
#define CURSOR_OPT_INSENSITIVE
Definition: parsenodes.h:3289
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:3287
#define CURSOR_OPT_HOLD
Definition: parsenodes.h:3291
#define CURSOR_OPT_ASENSITIVE
Definition: parsenodes.h:3290
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:3288
#define linitial(l)
Definition: pg_list.h:178

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

Referenced by transformStmt().

◆ transformDeleteStmt()

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

Definition at line 508 of file analyze.c.

509 {
510  Query *qry = makeNode(Query);
511  ParseNamespaceItem *nsitem;
512  Node *qual;
513 
514  qry->commandType = CMD_DELETE;
515 
516  /* process the WITH clause independently of all else */
517  if (stmt->withClause)
518  {
519  qry->hasRecursive = stmt->withClause->recursive;
520  qry->cteList = transformWithClause(pstate, stmt->withClause);
521  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
522  }
523 
524  /* set up range table with just the result rel */
525  qry->resultRelation = setTargetTable(pstate, stmt->relation,
526  stmt->relation->inh,
527  true,
528  ACL_DELETE);
529  nsitem = pstate->p_target_nsitem;
530 
531  /* there's no DISTINCT in DELETE */
532  qry->distinctClause = NIL;
533 
534  /* subqueries in USING cannot access the result relation */
535  nsitem->p_lateral_only = true;
536  nsitem->p_lateral_ok = false;
537 
538  /*
539  * The USING clause is non-standard SQL syntax, and is equivalent in
540  * functionality to the FROM list that can be specified for UPDATE. The
541  * USING keyword is used rather than FROM because FROM is already a
542  * keyword in the DELETE syntax.
543  */
544  transformFromClause(pstate, stmt->usingClause);
545 
546  /* remaining clauses can reference the result relation normally */
547  nsitem->p_lateral_only = false;
548  nsitem->p_lateral_ok = true;
549 
550  qual = transformWhereClause(pstate, stmt->whereClause,
551  EXPR_KIND_WHERE, "WHERE");
552 
553  qry->returningList = transformReturningList(pstate, stmt->returningList,
555 
556  /* done building the range table and jointree */
557  qry->rtable = pstate->p_rtable;
558  qry->rteperminfos = pstate->p_rteperminfos;
559  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
560 
561  qry->hasSubLinks = pstate->p_hasSubLinks;
562  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
563  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
564  qry->hasAggs = pstate->p_hasAggs;
565 
566  assign_query_collations(pstate, qry);
567 
568  /* this must be done after collations, for reliable comparison of exprs */
569  if (pstate->p_hasAggs)
570  parseCheckAggregates(pstate, qry);
571 
572  return qry;
573 }
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:287
@ CMD_DELETE
Definition: nodes.h:268
void parseCheckAggregates(ParseState *pstate, Query *qry)
Definition: parse_agg.c:1080
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
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:180
void assign_query_collations(ParseState *pstate, Query *query)
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:109
@ EXPR_KIND_WHERE
Definition: parse_node.h:46
@ EXPR_KIND_RETURNING
Definition: parse_node.h:64
#define ACL_DELETE
Definition: parsenodes.h:79
List * transformReturningList(ParseState *pstate, List *returningList, ParseExprKind exprKind)
Definition: analyze.c:2560
bool p_hasTargetSRFs
Definition: parse_node.h:225
bool p_hasWindowFuncs
Definition: parse_node.h:224
ParseNamespaceItem * p_target_nsitem
Definition: parse_node.h:208
bool p_hasModifyingCTE
Definition: parse_node.h:227
List * p_rteperminfos
Definition: parse_node.h:195
bool p_hasSubLinks
Definition: parse_node.h:226
List * p_joinlist
Definition: parse_node.h:199
bool p_hasAggs
Definition: parse_node.h:223
FromExpr * jointree
Definition: parsenodes.h:175
List * returningList
Definition: parsenodes.h:198
List * cteList
Definition: parsenodes.h:166
List * rtable
Definition: parsenodes.h:168

References ACL_DELETE, assign_query_collations(), CMD_DELETE, Query::commandType, Query::cteList, Query::distinctClause, EXPR_KIND_RETURNING, EXPR_KIND_WHERE, 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_rteperminfos, ParseState::p_target_nsitem, parseCheckAggregates(), Query::returningList, Query::rtable, setTargetTable(), stmt, transformFromClause(), transformReturningList(), transformWhereClause(), and transformWithClause().

Referenced by transformStmt().

◆ transformExplainStmt()

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

Definition at line 2961 of file analyze.c.

2962 {
2963  Query *result;
2964  bool generic_plan = false;
2965  Oid *paramTypes = NULL;
2966  int numParams = 0;
2967 
2968  /*
2969  * If we have no external source of parameter definitions, and the
2970  * GENERIC_PLAN option is specified, then accept variable parameter
2971  * definitions (similarly to PREPARE, for example).
2972  */
2973  if (pstate->p_paramref_hook == NULL)
2974  {
2975  ListCell *lc;
2976 
2977  foreach(lc, stmt->options)
2978  {
2979  DefElem *opt = (DefElem *) lfirst(lc);
2980 
2981  if (strcmp(opt->defname, "generic_plan") == 0)
2982  generic_plan = defGetBoolean(opt);
2983  /* don't "break", as we want the last value */
2984  }
2985  if (generic_plan)
2986  setup_parse_variable_parameters(pstate, &paramTypes, &numParams);
2987  }
2988 
2989  /* transform contained query, allowing SELECT INTO */
2990  stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
2991 
2992  /* make sure all is well with parameter types */
2993  if (generic_plan)
2994  check_variable_parameters(pstate, (Query *) stmt->query);
2995 
2996  /* represent the command as a utility Query */
2997  result = makeNode(Query);
2998  result->commandType = CMD_UTILITY;
2999  result->utilityStmt = (Node *) stmt;
3000 
3001  return result;
3002 }
bool defGetBoolean(DefElem *def)
Definition: define.c:107
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:272
char * defname
Definition: parsenodes.h:815
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:237

References check_variable_parameters(), CMD_UTILITY, Query::commandType, defGetBoolean(), DefElem::defname, lfirst, makeNode, ParseState::p_paramref_hook, setup_parse_variable_parameters(), stmt, transformOptionalSelectInto(), and Query::utilityStmt.

Referenced by transformStmt().

◆ transformInsertRow()

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

Definition at line 1008 of file analyze.c.

1011 {
1012  List *result;
1013  ListCell *lc;
1014  ListCell *icols;
1015  ListCell *attnos;
1016 
1017  /*
1018  * Check length of expr list. It must not have more expressions than
1019  * there are target columns. We allow fewer, but only if no explicit
1020  * columns list was given (the remaining columns are implicitly
1021  * defaulted). Note we must check this *after* transformation because
1022  * that could expand '*' into multiple items.
1023  */
1024  if (list_length(exprlist) > list_length(icolumns))
1025  ereport(ERROR,
1026  (errcode(ERRCODE_SYNTAX_ERROR),
1027  errmsg("INSERT has more expressions than target columns"),
1028  parser_errposition(pstate,
1029  exprLocation(list_nth(exprlist,
1030  list_length(icolumns))))));
1031  if (stmtcols != NIL &&
1032  list_length(exprlist) < list_length(icolumns))
1033  {
1034  /*
1035  * We can get here for cases like INSERT ... SELECT (a,b,c) FROM ...
1036  * where the user accidentally created a RowExpr instead of separate
1037  * columns. Add a suitable hint if that seems to be the problem,
1038  * because the main error message is quite misleading for this case.
1039  * (If there's no stmtcols, you'll get something about data type
1040  * mismatch, which is less misleading so we don't worry about giving a
1041  * hint in that case.)
1042  */
1043  ereport(ERROR,
1044  (errcode(ERRCODE_SYNTAX_ERROR),
1045  errmsg("INSERT has more target columns than expressions"),
1046  ((list_length(exprlist) == 1 &&
1047  count_rowexpr_columns(pstate, linitial(exprlist)) ==
1048  list_length(icolumns)) ?
1049  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),
1050  parser_errposition(pstate,
1051  exprLocation(list_nth(icolumns,
1052  list_length(exprlist))))));
1053  }
1054 
1055  /*
1056  * Prepare columns for assignment to target table.
1057  */
1058  result = NIL;
1059  forthree(lc, exprlist, icols, icolumns, attnos, attrnos)
1060  {
1061  Expr *expr = (Expr *) lfirst(lc);
1062  ResTarget *col = lfirst_node(ResTarget, icols);
1063  int attno = lfirst_int(attnos);
1064 
1065  expr = transformAssignedExpr(pstate, expr,
1067  col->name,
1068  attno,
1069  col->indirection,
1070  col->location);
1071 
1072  if (strip_indirection)
1073  {
1074  /*
1075  * We need to remove top-level FieldStores and SubscriptingRefs,
1076  * as well as any CoerceToDomain appearing above one of those ---
1077  * but not a CoerceToDomain that isn't above one of those.
1078  */
1079  while (expr)
1080  {
1081  Expr *subexpr = expr;
1082 
1083  while (IsA(subexpr, CoerceToDomain))
1084  {
1085  subexpr = ((CoerceToDomain *) subexpr)->arg;
1086  }
1087  if (IsA(subexpr, FieldStore))
1088  {
1089  FieldStore *fstore = (FieldStore *) subexpr;
1090 
1091  expr = (Expr *) linitial(fstore->newvals);
1092  }
1093  else if (IsA(subexpr, SubscriptingRef))
1094  {
1095  SubscriptingRef *sbsref = (SubscriptingRef *) subexpr;
1096 
1097  if (sbsref->refassgnexpr == NULL)
1098  break;
1099 
1100  expr = sbsref->refassgnexpr;
1101  }
1102  else
1103  break;
1104  }
1105  }
1106 
1107  result = lappend(result, expr);
1108  }
1109 
1110  return result;
1111 }
int errhint(const char *fmt,...)
Definition: elog.c:1317
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1386
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
@ EXPR_KIND_INSERT_TARGET
Definition: parse_node.h:55
Expr * transformAssignedExpr(ParseState *pstate, Expr *expr, ParseExprKind exprKind, const char *colname, int attrno, List *indirection, int location)
Definition: parse_target.c:452
static int count_rowexpr_columns(ParseState *pstate, Node *expr)
Definition: analyze.c:1295
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define lfirst_int(lc)
Definition: pg_list.h:173
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:563
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
List * newvals
Definition: primnodes.h:1160
ParseLoc location
Definition: parsenodes.h:520
List * indirection
Definition: parsenodes.h:518
char * name
Definition: parsenodes.h:517
Expr * refassgnexpr
Definition: primnodes.h:703

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(), and transformMergeStmt().

◆ transformInsertStmt()

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

Definition at line 580 of file analyze.c.

581 {
582  Query *qry = makeNode(Query);
583  SelectStmt *selectStmt = (SelectStmt *) stmt->selectStmt;
584  List *exprList = NIL;
585  bool isGeneralSelect;
586  List *sub_rtable;
587  List *sub_rteperminfos;
588  List *sub_namespace;
589  List *icolumns;
590  List *attrnos;
591  ParseNamespaceItem *nsitem;
592  RTEPermissionInfo *perminfo;
593  ListCell *icols;
594  ListCell *attnos;
595  ListCell *lc;
596  bool isOnConflictUpdate;
597  AclMode targetPerms;
598 
599  /* There can't be any outer WITH to worry about */
600  Assert(pstate->p_ctenamespace == NIL);
601 
602  qry->commandType = CMD_INSERT;
603  pstate->p_is_insert = true;
604 
605  /* process the WITH clause independently of all else */
606  if (stmt->withClause)
607  {
608  qry->hasRecursive = stmt->withClause->recursive;
609  qry->cteList = transformWithClause(pstate, stmt->withClause);
610  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
611  }
612 
613  qry->override = stmt->override;
614 
615  isOnConflictUpdate = (stmt->onConflictClause &&
616  stmt->onConflictClause->action == ONCONFLICT_UPDATE);
617 
618  /*
619  * We have three cases to deal with: DEFAULT VALUES (selectStmt == NULL),
620  * VALUES list, or general SELECT input. We special-case VALUES, both for
621  * efficiency and so we can handle DEFAULT specifications.
622  *
623  * The grammar allows attaching ORDER BY, LIMIT, FOR UPDATE, or WITH to a
624  * VALUES clause. If we have any of those, treat it as a general SELECT;
625  * so it will work, but you can't use DEFAULT items together with those.
626  */
627  isGeneralSelect = (selectStmt && (selectStmt->valuesLists == NIL ||
628  selectStmt->sortClause != NIL ||
629  selectStmt->limitOffset != NULL ||
630  selectStmt->limitCount != NULL ||
631  selectStmt->lockingClause != NIL ||
632  selectStmt->withClause != NULL));
633 
634  /*
635  * If a non-nil rangetable/namespace was passed in, and we are doing
636  * INSERT/SELECT, arrange to pass the rangetable/rteperminfos/namespace
637  * down to the SELECT. This can only happen if we are inside a CREATE
638  * RULE, and in that case we want the rule's OLD and NEW rtable entries to
639  * appear as part of the SELECT's rtable, not as outer references for it.
640  * (Kluge!) The SELECT's joinlist is not affected however. We must do
641  * this before adding the target table to the INSERT's rtable.
642  */
643  if (isGeneralSelect)
644  {
645  sub_rtable = pstate->p_rtable;
646  pstate->p_rtable = NIL;
647  sub_rteperminfos = pstate->p_rteperminfos;
648  pstate->p_rteperminfos = NIL;
649  sub_namespace = pstate->p_namespace;
650  pstate->p_namespace = NIL;
651  }
652  else
653  {
654  sub_rtable = NIL; /* not used, but keep compiler quiet */
655  sub_rteperminfos = NIL;
656  sub_namespace = NIL;
657  }
658 
659  /*
660  * Must get write lock on INSERT target table before scanning SELECT, else
661  * we will grab the wrong kind of initial lock if the target table is also
662  * mentioned in the SELECT part. Note that the target table is not added
663  * to the joinlist or namespace.
664  */
665  targetPerms = ACL_INSERT;
666  if (isOnConflictUpdate)
667  targetPerms |= ACL_UPDATE;
668  qry->resultRelation = setTargetTable(pstate, stmt->relation,
669  false, false, targetPerms);
670 
671  /* Validate stmt->cols list, or build default list if no list given */
672  icolumns = checkInsertTargets(pstate, stmt->cols, &attrnos);
673  Assert(list_length(icolumns) == list_length(attrnos));
674 
675  /*
676  * Determine which variant of INSERT we have.
677  */
678  if (selectStmt == NULL)
679  {
680  /*
681  * We have INSERT ... DEFAULT VALUES. We can handle this case by
682  * emitting an empty targetlist --- all columns will be defaulted when
683  * the planner expands the targetlist.
684  */
685  exprList = NIL;
686  }
687  else if (isGeneralSelect)
688  {
689  /*
690  * We make the sub-pstate a child of the outer pstate so that it can
691  * see any Param definitions supplied from above. Since the outer
692  * pstate's rtable and namespace are presently empty, there are no
693  * side-effects of exposing names the sub-SELECT shouldn't be able to
694  * see.
695  */
696  ParseState *sub_pstate = make_parsestate(pstate);
697  Query *selectQuery;
698 
699  /*
700  * Process the source SELECT.
701  *
702  * It is important that this be handled just like a standalone SELECT;
703  * otherwise the behavior of SELECT within INSERT might be different
704  * from a stand-alone SELECT. (Indeed, Postgres up through 6.5 had
705  * bugs of just that nature...)
706  *
707  * The sole exception is that we prevent resolving unknown-type
708  * outputs as TEXT. This does not change the semantics since if the
709  * column type matters semantically, it would have been resolved to
710  * something else anyway. Doing this lets us resolve such outputs as
711  * the target column's type, which we handle below.
712  */
713  sub_pstate->p_rtable = sub_rtable;
714  sub_pstate->p_rteperminfos = sub_rteperminfos;
715  sub_pstate->p_joinexprs = NIL; /* sub_rtable has no joins */
716  sub_pstate->p_nullingrels = NIL;
717  sub_pstate->p_namespace = sub_namespace;
718  sub_pstate->p_resolve_unknowns = false;
719 
720  selectQuery = transformStmt(sub_pstate, stmt->selectStmt);
721 
722  free_parsestate(sub_pstate);
723 
724  /* The grammar should have produced a SELECT */
725  if (!IsA(selectQuery, Query) ||
726  selectQuery->commandType != CMD_SELECT)
727  elog(ERROR, "unexpected non-SELECT command in INSERT ... SELECT");
728 
729  /*
730  * Make the source be a subquery in the INSERT's rangetable, and add
731  * it to the INSERT's joinlist (but not the namespace).
732  */
733  nsitem = addRangeTableEntryForSubquery(pstate,
734  selectQuery,
735  makeAlias("*SELECT*", NIL),
736  false,
737  false);
738  addNSItemToQuery(pstate, nsitem, true, false, false);
739 
740  /*----------
741  * Generate an expression list for the INSERT that selects all the
742  * non-resjunk columns from the subquery. (INSERT's tlist must be
743  * separate from the subquery's tlist because we may add columns,
744  * insert datatype coercions, etc.)
745  *
746  * HACK: unknown-type constants and params in the SELECT's targetlist
747  * are copied up as-is rather than being referenced as subquery
748  * outputs. This is to ensure that when we try to coerce them to
749  * the target column's datatype, the right things happen (see
750  * special cases in coerce_type). Otherwise, this fails:
751  * INSERT INTO foo SELECT 'bar', ... FROM baz
752  *----------
753  */
754  exprList = NIL;
755  foreach(lc, selectQuery->targetList)
756  {
757  TargetEntry *tle = (TargetEntry *) lfirst(lc);
758  Expr *expr;
759 
760  if (tle->resjunk)
761  continue;
762  if (tle->expr &&
763  (IsA(tle->expr, Const) || IsA(tle->expr, Param)) &&
764  exprType((Node *) tle->expr) == UNKNOWNOID)
765  expr = tle->expr;
766  else
767  {
768  Var *var = makeVarFromTargetEntry(nsitem->p_rtindex, tle);
769 
770  var->location = exprLocation((Node *) tle->expr);
771  expr = (Expr *) var;
772  }
773  exprList = lappend(exprList, expr);
774  }
775 
776  /* Prepare row for assignment to target table */
777  exprList = transformInsertRow(pstate, exprList,
778  stmt->cols,
779  icolumns, attrnos,
780  false);
781  }
782  else if (list_length(selectStmt->valuesLists) > 1)
783  {
784  /*
785  * Process INSERT ... VALUES with multiple VALUES sublists. We
786  * generate a VALUES RTE holding the transformed expression lists, and
787  * build up a targetlist containing Vars that reference the VALUES
788  * RTE.
789  */
790  List *exprsLists = NIL;
791  List *coltypes = NIL;
792  List *coltypmods = NIL;
793  List *colcollations = NIL;
794  int sublist_length = -1;
795  bool lateral = false;
796 
797  Assert(selectStmt->intoClause == NULL);
798 
799  foreach(lc, selectStmt->valuesLists)
800  {
801  List *sublist = (List *) lfirst(lc);
802 
803  /*
804  * Do basic expression transformation (same as a ROW() expr, but
805  * allow SetToDefault at top level)
806  */
807  sublist = transformExpressionList(pstate, sublist,
808  EXPR_KIND_VALUES, true);
809 
810  /*
811  * All the sublists must be the same length, *after*
812  * transformation (which might expand '*' into multiple items).
813  * The VALUES RTE can't handle anything different.
814  */
815  if (sublist_length < 0)
816  {
817  /* Remember post-transformation length of first sublist */
818  sublist_length = list_length(sublist);
819  }
820  else if (sublist_length != list_length(sublist))
821  {
822  ereport(ERROR,
823  (errcode(ERRCODE_SYNTAX_ERROR),
824  errmsg("VALUES lists must all be the same length"),
825  parser_errposition(pstate,
826  exprLocation((Node *) sublist))));
827  }
828 
829  /*
830  * Prepare row for assignment to target table. We process any
831  * indirection on the target column specs normally but then strip
832  * off the resulting field/array assignment nodes, since we don't
833  * want the parsed statement to contain copies of those in each
834  * VALUES row. (It's annoying to have to transform the
835  * indirection specs over and over like this, but avoiding it
836  * would take some really messy refactoring of
837  * transformAssignmentIndirection.)
838  */
839  sublist = transformInsertRow(pstate, sublist,
840  stmt->cols,
841  icolumns, attrnos,
842  true);
843 
844  /*
845  * We must assign collations now because assign_query_collations
846  * doesn't process rangetable entries. We just assign all the
847  * collations independently in each row, and don't worry about
848  * whether they are consistent vertically. The outer INSERT query
849  * isn't going to care about the collations of the VALUES columns,
850  * so it's not worth the effort to identify a common collation for
851  * each one here. (But note this does have one user-visible
852  * consequence: INSERT ... VALUES won't complain about conflicting
853  * explicit COLLATEs in a column, whereas the same VALUES
854  * construct in another context would complain.)
855  */
856  assign_list_collations(pstate, sublist);
857 
858  exprsLists = lappend(exprsLists, sublist);
859  }
860 
861  /*
862  * Construct column type/typmod/collation lists for the VALUES RTE.
863  * Every expression in each column has been coerced to the type/typmod
864  * of the corresponding target column or subfield, so it's sufficient
865  * to look at the exprType/exprTypmod of the first row. We don't care
866  * about the collation labeling, so just fill in InvalidOid for that.
867  */
868  foreach(lc, (List *) linitial(exprsLists))
869  {
870  Node *val = (Node *) lfirst(lc);
871 
872  coltypes = lappend_oid(coltypes, exprType(val));
873  coltypmods = lappend_int(coltypmods, exprTypmod(val));
874  colcollations = lappend_oid(colcollations, InvalidOid);
875  }
876 
877  /*
878  * Ordinarily there can't be any current-level Vars in the expression
879  * lists, because the namespace was empty ... but if we're inside
880  * CREATE RULE, then NEW/OLD references might appear. In that case we
881  * have to mark the VALUES RTE as LATERAL.
882  */
883  if (list_length(pstate->p_rtable) != 1 &&
884  contain_vars_of_level((Node *) exprsLists, 0))
885  lateral = true;
886 
887  /*
888  * Generate the VALUES RTE
889  */
890  nsitem = addRangeTableEntryForValues(pstate, exprsLists,
891  coltypes, coltypmods, colcollations,
892  NULL, lateral, true);
893  addNSItemToQuery(pstate, nsitem, true, false, false);
894 
895  /*
896  * Generate list of Vars referencing the RTE
897  */
898  exprList = expandNSItemVars(pstate, nsitem, 0, -1, NULL);
899 
900  /*
901  * Re-apply any indirection on the target column specs to the Vars
902  */
903  exprList = transformInsertRow(pstate, exprList,
904  stmt->cols,
905  icolumns, attrnos,
906  false);
907  }
908  else
909  {
910  /*
911  * Process INSERT ... VALUES with a single VALUES sublist. We treat
912  * this case separately for efficiency. The sublist is just computed
913  * directly as the Query's targetlist, with no VALUES RTE. So it
914  * works just like a SELECT without any FROM.
915  */
916  List *valuesLists = selectStmt->valuesLists;
917 
918  Assert(list_length(valuesLists) == 1);
919  Assert(selectStmt->intoClause == NULL);
920 
921  /*
922  * Do basic expression transformation (same as a ROW() expr, but allow
923  * SetToDefault at top level)
924  */
925  exprList = transformExpressionList(pstate,
926  (List *) linitial(valuesLists),
928  true);
929 
930  /* Prepare row for assignment to target table */
931  exprList = transformInsertRow(pstate, exprList,
932  stmt->cols,
933  icolumns, attrnos,
934  false);
935  }
936 
937  /*
938  * Generate query's target list using the computed list of expressions.
939  * Also, mark all the target columns as needing insert permissions.
940  */
941  perminfo = pstate->p_target_nsitem->p_perminfo;
942  qry->targetList = NIL;
943  Assert(list_length(exprList) <= list_length(icolumns));
944  forthree(lc, exprList, icols, icolumns, attnos, attrnos)
945  {
946  Expr *expr = (Expr *) lfirst(lc);
947  ResTarget *col = lfirst_node(ResTarget, icols);
948  AttrNumber attr_num = (AttrNumber) lfirst_int(attnos);
949  TargetEntry *tle;
950 
951  tle = makeTargetEntry(expr,
952  attr_num,
953  col->name,
954  false);
955  qry->targetList = lappend(qry->targetList, tle);
956 
957  perminfo->insertedCols = bms_add_member(perminfo->insertedCols,
959  }
960 
961  /*
962  * If we have any clauses yet to process, set the query namespace to
963  * contain only the target relation, removing any entries added in a
964  * sub-SELECT or VALUES list.
965  */
966  if (stmt->onConflictClause || stmt->returningList)
967  {
968  pstate->p_namespace = NIL;
969  addNSItemToQuery(pstate, pstate->p_target_nsitem,
970  false, true, true);
971  }
972 
973  /* Process ON CONFLICT, if any. */
974  if (stmt->onConflictClause)
976  stmt->onConflictClause);
977 
978  /* Process RETURNING, if any. */
979  if (stmt->returningList)
981  stmt->returningList,
983 
984  /* done building the range table and jointree */
985  qry->rtable = pstate->p_rtable;
986  qry->rteperminfos = pstate->p_rteperminfos;
987  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
988 
989  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
990  qry->hasSubLinks = pstate->p_hasSubLinks;
991 
992  assign_query_collations(pstate, qry);
993 
994  return qry;
995 }
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
long val
Definition: informix.c:670
List * lappend_int(List *list, int datum)
Definition: list.c:357
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:389
Var * makeVarFromTargetEntry(int varno, TargetEntry *tle)
Definition: makefuncs.c:105
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:298
@ ONCONFLICT_UPDATE
Definition: nodes.h:419
@ CMD_INSERT
Definition: nodes.h:267
void assign_list_collations(ParseState *pstate, List *exprs)
@ EXPR_KIND_VALUES
Definition: parse_node.h:66
@ EXPR_KIND_VALUES_SINGLE
Definition: parse_node.h:67
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
ParseNamespaceItem * addRangeTableEntryForSubquery(ParseState *pstate, Query *subquery, Alias *alias, bool lateral, bool inFromCl)
ParseNamespaceItem * addRangeTableEntryForValues(ParseState *pstate, List *exprs, List *coltypes, List *coltypmods, List *colcollations, Alias *alias, bool lateral, bool inFromCl)
List * expandNSItemVars(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, int location, List **colnames)
List * checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
List * transformExpressionList(ParseState *pstate, List *exprlist, ParseExprKind exprKind, bool allowDefault)
Definition: parse_target.c:220
uint64 AclMode
Definition: parsenodes.h:74
#define ACL_INSERT
Definition: parsenodes.h:76
#define ACL_UPDATE
Definition: parsenodes.h:78
static OnConflictExpr * transformOnConflictClause(ParseState *pstate, OnConflictClause *onConflictClause)
Definition: analyze.c:1118
List * transformInsertRow(ParseState *pstate, List *exprlist, List *stmtcols, List *icolumns, List *attrnos, bool strip_indirection)
Definition: analyze.c:1008
RTEPermissionInfo * p_perminfo
Definition: parse_node.h:289
List * p_ctenamespace
Definition: parse_node.h:204
List * p_nullingrels
Definition: parse_node.h:198
List * p_namespace
Definition: parse_node.h:201
bool p_is_insert
Definition: parse_node.h:209
List * p_joinexprs
Definition: parse_node.h:197
OnConflictExpr * onConflict
Definition: parsenodes.h:196
List * sortClause
Definition: parsenodes.h:2151
IntoClause * intoClause
Definition: parsenodes.h:2128
Node * limitOffset
Definition: parsenodes.h:2152
List * lockingClause
Definition: parsenodes.h:2155
Node * limitCount
Definition: parsenodes.h:2153
List * valuesLists
Definition: parsenodes.h:2145
WithClause * withClause
Definition: parsenodes.h:2156
ParseLoc location
Definition: primnodes.h:293
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:441

References ACL_INSERT, ACL_UPDATE, addNSItemToQuery(), addRangeTableEntryForSubquery(), Assert, checkInsertTargets(), CMD_INSERT, CMD_SELECT, Query::commandType, Query::cteList, elog, ERROR, TargetEntry::expr, exprLocation(), exprType(), free_parsestate(), IsA, lappend(), lfirst, SelectStmt::limitCount, SelectStmt::limitOffset, list_length(), Var::location, SelectStmt::lockingClause, make_parsestate(), makeAlias(), makeNode, makeVarFromTargetEntry(), NIL, ONCONFLICT_UPDATE, ParseState::p_ctenamespace, ParseState::p_hasModifyingCTE, ParseState::p_is_insert, ParseState::p_joinexprs, ParseState::p_namespace, ParseState::p_nullingrels, ParseState::p_resolve_unknowns, ParseState::p_rtable, ParseState::p_rteperminfos, setTargetTable(), SelectStmt::sortClause, stmt, Query::targetList, transformInsertRow(), transformStmt(), transformWithClause(), SelectStmt::valuesLists, and SelectStmt::withClause.

Referenced by transformStmt().

◆ transformLockingClause()

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

Definition at line 3302 of file analyze.c.

3304 {
3305  List *lockedRels = lc->lockedRels;
3306  ListCell *l;
3307  ListCell *rt;
3308  Index i;
3309  LockingClause *allrels;
3310 
3311  CheckSelectLocking(qry, lc->strength);
3312 
3313  /* make a clause we can pass down to subqueries to select all rels */
3314  allrels = makeNode(LockingClause);
3315  allrels->lockedRels = NIL; /* indicates all rels */
3316  allrels->strength = lc->strength;
3317  allrels->waitPolicy = lc->waitPolicy;
3318 
3319  if (lockedRels == NIL)
3320  {
3321  /*
3322  * Lock all regular tables used in query and its subqueries. We
3323  * examine inFromCl to exclude auto-added RTEs, particularly NEW/OLD
3324  * in rules. This is a bit of an abuse of a mostly-obsolete flag, but
3325  * it's convenient. We can't rely on the namespace mechanism that has
3326  * largely replaced inFromCl, since for example we need to lock
3327  * base-relation RTEs even if they are masked by upper joins.
3328  */
3329  i = 0;
3330  foreach(rt, qry->rtable)
3331  {
3332  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
3333 
3334  ++i;
3335  if (!rte->inFromCl)
3336  continue;
3337  switch (rte->rtekind)
3338  {
3339  case RTE_RELATION:
3340  {
3341  RTEPermissionInfo *perminfo;
3342 
3343  applyLockingClause(qry, i,
3344  lc->strength,
3345  lc->waitPolicy,
3346  pushedDown);
3347  perminfo = getRTEPermissionInfo(qry->rteperminfos, rte);
3348  perminfo->requiredPerms |= ACL_SELECT_FOR_UPDATE;
3349  }
3350  break;
3351  case RTE_SUBQUERY:
3352  applyLockingClause(qry, i, lc->strength, lc->waitPolicy,
3353  pushedDown);
3354 
3355  /*
3356  * FOR UPDATE/SHARE of subquery is propagated to all of
3357  * subquery's rels, too. We could do this later (based on
3358  * the marking of the subquery RTE) but it is convenient
3359  * to have local knowledge in each query level about which
3360  * rels need to be opened with RowShareLock.
3361  */
3362  transformLockingClause(pstate, rte->subquery,
3363  allrels, true);
3364  break;
3365  default:
3366  /* ignore JOIN, SPECIAL, FUNCTION, VALUES, CTE RTEs */
3367  break;
3368  }
3369  }
3370  }
3371  else
3372  {
3373  /*
3374  * Lock just the named tables. As above, we allow locking any base
3375  * relation regardless of alias-visibility rules, so we need to
3376  * examine inFromCl to exclude OLD/NEW.
3377  */
3378  foreach(l, lockedRels)
3379  {
3380  RangeVar *thisrel = (RangeVar *) lfirst(l);
3381 
3382  /* For simplicity we insist on unqualified alias names here */
3383  if (thisrel->catalogname || thisrel->schemaname)
3384  ereport(ERROR,
3385  (errcode(ERRCODE_SYNTAX_ERROR),
3386  /*------
3387  translator: %s is a SQL row locking clause such as FOR UPDATE */
3388  errmsg("%s must specify unqualified relation names",
3389  LCS_asString(lc->strength)),
3390  parser_errposition(pstate, thisrel->location)));
3391 
3392  i = 0;
3393  foreach(rt, qry->rtable)
3394  {
3395  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
3396  char *rtename = rte->eref->aliasname;
3397 
3398  ++i;
3399  if (!rte->inFromCl)
3400  continue;
3401 
3402  /*
3403  * A join RTE without an alias is not visible as a relation
3404  * name and needs to be skipped (otherwise it might hide a
3405  * base relation with the same name), except if it has a USING
3406  * alias, which *is* visible.
3407  *
3408  * Subquery and values RTEs without aliases are never visible
3409  * as relation names and must always be skipped.
3410  */
3411  if (rte->alias == NULL)
3412  {
3413  if (rte->rtekind == RTE_JOIN)
3414  {
3415  if (rte->join_using_alias == NULL)
3416  continue;
3417  rtename = rte->join_using_alias->aliasname;
3418  }
3419  else if (rte->rtekind == RTE_SUBQUERY ||
3420  rte->rtekind == RTE_VALUES)
3421  continue;
3422  }
3423 
3424  if (strcmp(rtename, thisrel->relname) == 0)
3425  {
3426  switch (rte->rtekind)
3427  {
3428  case RTE_RELATION:
3429  {
3430  RTEPermissionInfo *perminfo;
3431 
3432  applyLockingClause(qry, i,
3433  lc->strength,
3434  lc->waitPolicy,
3435  pushedDown);
3436  perminfo = getRTEPermissionInfo(qry->rteperminfos, rte);
3437  perminfo->requiredPerms |= ACL_SELECT_FOR_UPDATE;
3438  }
3439  break;
3440  case RTE_SUBQUERY:
3441  applyLockingClause(qry, i, lc->strength,
3442  lc->waitPolicy, pushedDown);
3443  /* see comment above */
3444  transformLockingClause(pstate, rte->subquery,
3445  allrels, true);
3446  break;
3447  case RTE_JOIN:
3448  ereport(ERROR,
3449  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3450  /*------
3451  translator: %s is a SQL row locking clause such as FOR UPDATE */
3452  errmsg("%s cannot be applied to a join",
3453  LCS_asString(lc->strength)),
3454  parser_errposition(pstate, thisrel->location)));
3455  break;
3456  case RTE_FUNCTION:
3457  ereport(ERROR,
3458  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3459  /*------
3460  translator: %s is a SQL row locking clause such as FOR UPDATE */
3461  errmsg("%s cannot be applied to a function",
3462  LCS_asString(lc->strength)),
3463  parser_errposition(pstate, thisrel->location)));
3464  break;
3465  case RTE_TABLEFUNC:
3466  ereport(ERROR,
3467  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3468  /*------
3469  translator: %s is a SQL row locking clause such as FOR UPDATE */
3470  errmsg("%s cannot be applied to a table function",
3471  LCS_asString(lc->strength)),
3472  parser_errposition(pstate, thisrel->location)));
3473  break;
3474  case RTE_VALUES:
3475  ereport(ERROR,
3476  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3477  /*------
3478  translator: %s is a SQL row locking clause such as FOR UPDATE */
3479  errmsg("%s cannot be applied to VALUES",
3480  LCS_asString(lc->strength)),
3481  parser_errposition(pstate, thisrel->location)));
3482  break;
3483  case RTE_CTE:
3484  ereport(ERROR,
3485  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3486  /*------
3487  translator: %s is a SQL row locking clause such as FOR UPDATE */
3488  errmsg("%s cannot be applied to a WITH query",
3489  LCS_asString(lc->strength)),
3490  parser_errposition(pstate, thisrel->location)));
3491  break;
3492  case RTE_NAMEDTUPLESTORE:
3493  ereport(ERROR,
3494  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3495  /*------
3496  translator: %s is a SQL row locking clause such as FOR UPDATE */
3497  errmsg("%s cannot be applied to a named tuplestore",
3498  LCS_asString(lc->strength)),
3499  parser_errposition(pstate, thisrel->location)));
3500  break;
3501 
3502  /* Shouldn't be possible to see RTE_RESULT here */
3503 
3504  default:
3505  elog(ERROR, "unrecognized RTE type: %d",
3506  (int) rte->rtekind);
3507  break;
3508  }
3509  break; /* out of foreach loop */
3510  }
3511  }
3512  if (rt == NULL)
3513  ereport(ERROR,
3515  /*------
3516  translator: %s is a SQL row locking clause such as FOR UPDATE */
3517  errmsg("relation \"%s\" in %s clause not found in FROM clause",
3518  thisrel->relname,
3519  LCS_asString(lc->strength)),
3520  parser_errposition(pstate, thisrel->location)));
3521  }
3522  }
3523 }
unsigned int Index
Definition: c.h:614
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ RTE_JOIN
Definition: parsenodes.h:1030
@ RTE_CTE
Definition: parsenodes.h:1034
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1035
@ RTE_VALUES
Definition: parsenodes.h:1033
@ RTE_FUNCTION
Definition: parsenodes.h:1031
@ RTE_TABLEFUNC
Definition: parsenodes.h:1032
@ RTE_RELATION
Definition: parsenodes.h:1028
#define ACL_SELECT_FOR_UPDATE
Definition: parsenodes.h:94
static void transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc, bool pushedDown)
Definition: analyze.c:3302
void CheckSelectLocking(Query *qry, LockClauseStrength strength)
Definition: analyze.c:3238
void applyLockingClause(Query *qry, Index rtindex, LockClauseStrength strength, LockWaitPolicy waitPolicy, bool pushedDown)
Definition: analyze.c:3529
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78
List * lockedRels
Definition: parsenodes.h:834
LockClauseStrength strength
Definition: parsenodes.h:835
LockWaitPolicy waitPolicy
Definition: parsenodes.h:836
AclMode requiredPerms
Definition: parsenodes.h:1295
char * relname
Definition: primnodes.h:82
char * catalogname
Definition: primnodes.h:76
ParseLoc location
Definition: primnodes.h:94
char * schemaname
Definition: primnodes.h:79

References ACL_SELECT_FOR_UPDATE, applyLockingClause(), RangeVar::catalogname, CheckSelectLocking(), elog, ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, getRTEPermissionInfo(), i, LCS_asString(), lfirst, RangeVar::location, LockingClause::lockedRels, makeNode, NIL, parser_errposition(), RangeVar::relname, RTEPermissionInfo::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 transformPLAssignStmt(), transformSelectStmt(), and transformSetOperationStmt().

◆ transformOnConflictClause()

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

Definition at line 1118 of file analyze.c.

1120 {
1121  ParseNamespaceItem *exclNSItem = NULL;
1122  List *arbiterElems;
1123  Node *arbiterWhere;
1124  Oid arbiterConstraint;
1125  List *onConflictSet = NIL;
1126  Node *onConflictWhere = NULL;
1127  int exclRelIndex = 0;
1128  List *exclRelTlist = NIL;
1129  OnConflictExpr *result;
1130 
1131  /*
1132  * If this is ON CONFLICT ... UPDATE, first create the range table entry
1133  * for the EXCLUDED pseudo relation, so that that will be present while
1134  * processing arbiter expressions. (You can't actually reference it from
1135  * there, but this provides a useful error message if you try.)
1136  */
1137  if (onConflictClause->action == ONCONFLICT_UPDATE)
1138  {
1139  Relation targetrel = pstate->p_target_relation;
1140  RangeTblEntry *exclRte;
1141 
1142  exclNSItem = addRangeTableEntryForRelation(pstate,
1143  targetrel,
1145  makeAlias("excluded", NIL),
1146  false, false);
1147  exclRte = exclNSItem->p_rte;
1148  exclRelIndex = exclNSItem->p_rtindex;
1149 
1150  /*
1151  * relkind is set to composite to signal that we're not dealing with
1152  * an actual relation, and no permission checks are required on it.
1153  * (We'll check the actual target relation, instead.)
1154  */
1155  exclRte->relkind = RELKIND_COMPOSITE_TYPE;
1156 
1157  /* Create EXCLUDED rel's targetlist for use by EXPLAIN */
1158  exclRelTlist = BuildOnConflictExcludedTargetlist(targetrel,
1159  exclRelIndex);
1160  }
1161 
1162  /* Process the arbiter clause, ON CONFLICT ON (...) */
1163  transformOnConflictArbiter(pstate, onConflictClause, &arbiterElems,
1164  &arbiterWhere, &arbiterConstraint);
1165 
1166  /* Process DO UPDATE */
1167  if (onConflictClause->action == ONCONFLICT_UPDATE)
1168  {
1169  /*
1170  * Expressions in the UPDATE targetlist need to be handled like UPDATE
1171  * not INSERT. We don't need to save/restore this because all INSERT
1172  * expressions have been parsed already.
1173  */
1174  pstate->p_is_insert = false;
1175 
1176  /*
1177  * Add the EXCLUDED pseudo relation to the query namespace, making it
1178  * available in the UPDATE subexpressions.
1179  */
1180  addNSItemToQuery(pstate, exclNSItem, false, true, true);
1181 
1182  /*
1183  * Now transform the UPDATE subexpressions.
1184  */
1185  onConflictSet =
1186  transformUpdateTargetList(pstate, onConflictClause->targetList);
1187 
1188  onConflictWhere = transformWhereClause(pstate,
1189  onConflictClause->whereClause,
1190  EXPR_KIND_WHERE, "WHERE");
1191 
1192  /*
1193  * Remove the EXCLUDED pseudo relation from the query namespace, since
1194  * it's not supposed to be available in RETURNING. (Maybe someday we
1195  * could allow that, and drop this step.)
1196  */
1197  Assert((ParseNamespaceItem *) llast(pstate->p_namespace) == exclNSItem);
1198  pstate->p_namespace = list_delete_last(pstate->p_namespace);
1199  }
1200 
1201  /* Finally, build ON CONFLICT DO [NOTHING | UPDATE] expression */
1202  result = makeNode(OnConflictExpr);
1203 
1204  result->action = onConflictClause->action;
1205  result->arbiterElems = arbiterElems;
1206  result->arbiterWhere = arbiterWhere;
1207  result->constraint = arbiterConstraint;
1208  result->onConflictSet = onConflictSet;
1209  result->onConflictWhere = onConflictWhere;
1210  result->exclRelIndex = exclRelIndex;
1211  result->exclRelTlist = exclRelTlist;
1212 
1213  return result;
1214 }
List * list_delete_last(List *list)
Definition: list.c:957
#define RowExclusiveLock
Definition: lockdefs.h:38
void transformOnConflictArbiter(ParseState *pstate, OnConflictClause *onConflictClause, List **arbiterExpr, Node **arbiterWhere, Oid *constraint)
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
List * transformUpdateTargetList(ParseState *pstate, List *origTlist)
Definition: analyze.c:2485
List * BuildOnConflictExcludedTargetlist(Relation targetrel, Index exclRelIndex)
Definition: analyze.c:1225
#define llast(l)
Definition: pg_list.h:198
OnConflictAction action
Definition: parsenodes.h:1627
List * arbiterElems
Definition: primnodes.h:2329
OnConflictAction action
Definition: primnodes.h:2326
List * onConflictSet
Definition: primnodes.h:2335
List * exclRelTlist
Definition: primnodes.h:2338
Node * onConflictWhere
Definition: primnodes.h:2336
Node * arbiterWhere
Definition: primnodes.h:2331
RangeTblEntry * p_rte
Definition: parse_node.h:287
Relation p_target_relation
Definition: parse_node.h:207

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

◆ transformOptionalSelectInto()

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

Definition at line 272 of file analyze.c.

273 {
274  if (IsA(parseTree, SelectStmt))
275  {
276  SelectStmt *stmt = (SelectStmt *) parseTree;
277 
278  /* If it's a set-operation tree, drill down to leftmost SelectStmt */
279  while (stmt && stmt->op != SETOP_NONE)
280  stmt = stmt->larg;
281  Assert(stmt && IsA(stmt, SelectStmt) && stmt->larg == NULL);
282 
283  if (stmt->intoClause)
284  {
286 
287  ctas->query = parseTree;
288  ctas->into = stmt->intoClause;
289  ctas->objtype = OBJECT_TABLE;
290  ctas->is_select_into = true;
291 
292  /*
293  * Remove the intoClause from the SelectStmt. This makes it safe
294  * for transformSelectStmt to complain if it finds intoClause set
295  * (implying that the INTO appeared in a disallowed place).
296  */
297  stmt->intoClause = NULL;
298 
299  parseTree = (Node *) ctas;
300  }
301  }
302 
303  return transformStmt(pstate, parseTree);
304 }
@ SETOP_NONE
Definition: parsenodes.h:2113
@ OBJECT_TABLE
Definition: parsenodes.h:2302
IntoClause * into
Definition: parsenodes.h:3897
ObjectType objtype
Definition: parsenodes.h:3898

References Assert, CreateTableAsStmt::into, CreateTableAsStmt::is_select_into, IsA, makeNode, OBJECT_TABLE, CreateTableAsStmt::objtype, CreateTableAsStmt::query, SETOP_NONE, stmt, and transformStmt().

Referenced by transformExplainStmt(), and transformTopLevelStmt().

◆ transformPLAssignStmt()

static Query * transformPLAssignStmt ( ParseState pstate,
PLAssignStmt stmt 
)
static

Definition at line 2619 of file analyze.c.

2620 {
2621  Query *qry = makeNode(Query);
2622  ColumnRef *cref = makeNode(ColumnRef);
2623  List *indirection = stmt->indirection;
2624  int nnames = stmt->nnames;
2625  SelectStmt *sstmt = stmt->val;
2626  Node *target;
2627  Oid targettype;
2628  int32 targettypmod;
2629  Oid targetcollation;
2630  List *tlist;
2631  TargetEntry *tle;
2632  Oid type_id;
2633  Node *qual;
2634  ListCell *l;
2635 
2636  /*
2637  * First, construct a ColumnRef for the target variable. If the target
2638  * has more than one dotted name, we have to pull the extra names out of
2639  * the indirection list.
2640  */
2641  cref->fields = list_make1(makeString(stmt->name));
2642  cref->location = stmt->location;
2643  if (nnames > 1)
2644  {
2645  /* avoid munging the raw parsetree */
2646  indirection = list_copy(indirection);
2647  while (--nnames > 0 && indirection != NIL)
2648  {
2649  Node *ind = (Node *) linitial(indirection);
2650 
2651  if (!IsA(ind, String))
2652  elog(ERROR, "invalid name count in PLAssignStmt");
2653  cref->fields = lappend(cref->fields, ind);
2654  indirection = list_delete_first(indirection);
2655  }
2656  }
2657 
2658  /*
2659  * Transform the target reference. Typically we will get back a Param
2660  * node, but there's no reason to be too picky about its type.
2661  */
2662  target = transformExpr(pstate, (Node *) cref,
2664  targettype = exprType(target);
2665  targettypmod = exprTypmod(target);
2666  targetcollation = exprCollation(target);
2667 
2668  /*
2669  * The rest mostly matches transformSelectStmt, except that we needn't
2670  * consider WITH or INTO, and we build a targetlist our own way.
2671  */
2672  qry->commandType = CMD_SELECT;
2673  pstate->p_is_insert = false;
2674 
2675  /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
2676  pstate->p_locking_clause = sstmt->lockingClause;
2677 
2678  /* make WINDOW info available for window functions, too */
2679  pstate->p_windowdefs = sstmt->windowClause;
2680 
2681  /* process the FROM clause */
2682  transformFromClause(pstate, sstmt->fromClause);
2683 
2684  /* initially transform the targetlist as if in SELECT */
2685  tlist = transformTargetList(pstate, sstmt->targetList,
2687 
2688  /* we should have exactly one targetlist item */
2689  if (list_length(tlist) != 1)
2690  ereport(ERROR,
2691  (errcode(ERRCODE_SYNTAX_ERROR),
2692  errmsg_plural("assignment source returned %d column",
2693  "assignment source returned %d columns",
2694  list_length(tlist),
2695  list_length(tlist))));
2696 
2697  tle = linitial_node(TargetEntry, tlist);
2698 
2699  /*
2700  * This next bit is similar to transformAssignedExpr; the key difference
2701  * is we use COERCION_PLPGSQL not COERCION_ASSIGNMENT.
2702  */
2703  type_id = exprType((Node *) tle->expr);
2704 
2706 
2707  if (indirection)
2708  {
2709  tle->expr = (Expr *)
2711  target,
2712  stmt->name,
2713  false,
2714  targettype,
2715  targettypmod,
2716  targetcollation,
2717  indirection,
2718  list_head(indirection),
2719  (Node *) tle->expr,
2721  exprLocation(target));
2722  }
2723  else if (targettype != type_id &&
2724  (targettype == RECORDOID || ISCOMPLEX(targettype)) &&
2725  (type_id == RECORDOID || ISCOMPLEX(type_id)))
2726  {
2727  /*
2728  * Hack: do not let coerce_to_target_type() deal with inconsistent
2729  * composite types. Just pass the expression result through as-is,
2730  * and let the PL/pgSQL executor do the conversion its way. This is
2731  * rather bogus, but it's needed for backwards compatibility.
2732  */
2733  }
2734  else
2735  {
2736  /*
2737  * For normal non-qualified target column, do type checking and
2738  * coercion.
2739  */
2740  Node *orig_expr = (Node *) tle->expr;
2741 
2742  tle->expr = (Expr *)
2743  coerce_to_target_type(pstate,
2744  orig_expr, type_id,
2745  targettype, targettypmod,
2748  -1);
2749  /* With COERCION_PLPGSQL, this error is probably unreachable */
2750  if (tle->expr == NULL)
2751  ereport(ERROR,
2752  (errcode(ERRCODE_DATATYPE_MISMATCH),
2753  errmsg("variable \"%s\" is of type %s"
2754  " but expression is of type %s",
2755  stmt->name,
2756  format_type_be(targettype),
2757  format_type_be(type_id)),
2758  errhint("You will need to rewrite or cast the expression."),
2759  parser_errposition(pstate, exprLocation(orig_expr))));
2760  }
2761 
2762  pstate->p_expr_kind = EXPR_KIND_NONE;
2763 
2764  qry->targetList = list_make1(tle);
2765 
2766  /* transform WHERE */
2767  qual = transformWhereClause(pstate, sstmt->whereClause,
2768  EXPR_KIND_WHERE, "WHERE");
2769 
2770  /* initial processing of HAVING clause is much like WHERE clause */
2771  qry->havingQual = transformWhereClause(pstate, sstmt->havingClause,
2772  EXPR_KIND_HAVING, "HAVING");
2773 
2774  /*
2775  * Transform sorting/grouping stuff. Do ORDER BY first because both
2776  * transformGroupClause and transformDistinctClause need the results. Note
2777  * that these functions can also change the targetList, so it's passed to
2778  * them by reference.
2779  */
2780  qry->sortClause = transformSortClause(pstate,
2781  sstmt->sortClause,
2782  &qry->targetList,
2784  false /* allow SQL92 rules */ );
2785 
2786  qry->groupClause = transformGroupClause(pstate,
2787  sstmt->groupClause,
2788  &qry->groupingSets,
2789  &qry->targetList,
2790  qry->sortClause,
2792  false /* allow SQL92 rules */ );
2793 
2794  if (sstmt->distinctClause == NIL)
2795  {
2796  qry->distinctClause = NIL;
2797  qry->hasDistinctOn = false;
2798  }
2799  else if (linitial(sstmt->distinctClause) == NULL)
2800  {
2801  /* We had SELECT DISTINCT */
2803  &qry->targetList,
2804  qry->sortClause,
2805  false);
2806  qry->hasDistinctOn = false;
2807  }
2808  else
2809  {
2810  /* We had SELECT DISTINCT ON */
2812  sstmt->distinctClause,
2813  &qry->targetList,
2814  qry->sortClause);
2815  qry->hasDistinctOn = true;
2816  }
2817 
2818  /* transform LIMIT */
2819  qry->limitOffset = transformLimitClause(pstate, sstmt->limitOffset,
2820  EXPR_KIND_OFFSET, "OFFSET",
2821  sstmt->limitOption);
2822  qry->limitCount = transformLimitClause(pstate, sstmt->limitCount,
2823  EXPR_KIND_LIMIT, "LIMIT",
2824  sstmt->limitOption);
2825  qry->limitOption = sstmt->limitOption;
2826 
2827  /* transform window clauses after we have seen all window functions */
2829  pstate->p_windowdefs,
2830  &qry->targetList);
2831 
2832  qry->rtable = pstate->p_rtable;
2833  qry->rteperminfos = pstate->p_rteperminfos;
2834  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2835 
2836  qry->hasSubLinks = pstate->p_hasSubLinks;
2837  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
2838  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2839  qry->hasAggs = pstate->p_hasAggs;
2840 
2841  foreach(l, sstmt->lockingClause)
2842  {
2843  transformLockingClause(pstate, qry,
2844  (LockingClause *) lfirst(l), false);
2845  }
2846 
2847  assign_query_collations(pstate, qry);
2848 
2849  /* this must be done after collations, for reliable comparison of exprs */
2850  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
2851  parseCheckAggregates(pstate, qry);
2852 
2853  return qry;
2854 }
signed int int32
Definition: c.h:494
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1180
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
List * list_copy(const List *oldlist)
Definition: list.c:1573
List * list_delete_first(List *list)
Definition: list.c:943
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:816
List * transformWindowDefinitions(ParseState *pstate, List *windowdefs, List **targetlist)
List * transformDistinctOnClause(ParseState *pstate, List *distinctlist, List **targetlist, List *sortClause)
Node * transformLimitClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName, LimitOption limitOption)
List * transformSortClause(ParseState *pstate, List *orderlist, List **targetlist, ParseExprKind exprKind, bool useSQL99)
List * transformGroupClause(ParseState *pstate, List *grouplist, List **groupingSets, List **targetlist, List *sortClause, ParseExprKind exprKind, bool useSQL99)
List * transformDistinctClause(ParseState *pstate, List **targetlist, List *sortClause, bool is_agg)
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:78
@ EXPR_KIND_ORDER_BY
Definition: parse_node.h:60
@ EXPR_KIND_OFFSET
Definition: parse_node.h:63
@ EXPR_KIND_HAVING
Definition: parse_node.h:47
@ EXPR_KIND_LIMIT
Definition: parse_node.h:62
@ EXPR_KIND_UPDATE_TARGET
Definition: parse_node.h:57
@ EXPR_KIND_SELECT_TARGET
Definition: parse_node.h:54
@ EXPR_KIND_NONE
Definition: parse_node.h:40
@ EXPR_KIND_GROUP_BY
Definition: parse_node.h:59
List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind)
Definition: parse_target.c:121
Node * transformAssignmentIndirection(ParseState *pstate, Node *basenode, const char *targetName, bool targetIsSubscripting, Oid targetTypeId, int32 targetTypMod, Oid targetCollation, List *indirection, ListCell *indirection_cell, Node *rhs, CoercionContext ccontext, int location)
Definition: parse_target.c:683
#define ISCOMPLEX(typeid)
Definition: parse_type.h:59
#define linitial_node(type, l)
Definition: pg_list.h:181
#define list_make1(x1)
Definition: pg_list.h:212
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:736
@ COERCION_PLPGSQL
Definition: primnodes.h:716
ParseLoc location
Definition: parsenodes.h:295
List * fields
Definition: parsenodes.h:294
ParseExprKind p_expr_kind
Definition: parse_node.h:211
List * p_windowdefs
Definition: parse_node.h:210
List * p_locking_clause
Definition: parse_node.h:214
Node * limitCount
Definition: parsenodes.h:214
Node * limitOffset
Definition: parsenodes.h:213
LimitOption limitOption
Definition: parsenodes.h:215
List * windowClause
Definition: parsenodes.h:207
List * sortClause
Definition: parsenodes.h:211
LimitOption limitOption
Definition: parsenodes.h:2154
List * targetList
Definition: parsenodes.h:2129
List * fromClause
Definition: parsenodes.h:2130
List * groupClause
Definition: parsenodes.h:2132
Node * havingClause
Definition: parsenodes.h:2134
List * windowClause
Definition: parsenodes.h:2135
List * distinctClause
Definition: parsenodes.h:2126
Node * whereClause
Definition: parsenodes.h:2131
Definition: value.h:64
String * makeString(char *str)
Definition: value.c:63

References assign_query_collations(), CMD_SELECT, COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_PLPGSQL, Query::commandType, Query::distinctClause, SelectStmt::distinctClause, elog, ereport, errcode(), errhint(), errmsg(), errmsg_plural(), ERROR, TargetEntry::expr, EXPR_KIND_GROUP_BY, EXPR_KIND_HAVING, EXPR_KIND_LIMIT, EXPR_KIND_NONE, EXPR_KIND_OFFSET, EXPR_KIND_ORDER_BY, EXPR_KIND_SELECT_TARGET, EXPR_KIND_UPDATE_TARGET, EXPR_KIND_WHERE, exprCollation(), exprLocation(), exprType(), exprTypmod(), ColumnRef::fields, format_type_be(), SelectStmt::fromClause, Query::groupClause, SelectStmt::groupClause, Query::groupingSets, SelectStmt::havingClause, Query::havingQual, IsA, ISCOMPLEX, Query::jointree, lappend(), lfirst, Query::limitCount, SelectStmt::limitCount, Query::limitOffset, SelectStmt::limitOffset, Query::limitOption, SelectStmt::limitOption, linitial, linitial_node, list_copy(), list_delete_first(), list_head(), list_length(), list_make1, ColumnRef::location, SelectStmt::lockingClause, makeFromExpr(), makeNode, makeString(), NIL, ParseState::p_expr_kind, ParseState::p_hasAggs, ParseState::p_hasSubLinks, ParseState::p_hasTargetSRFs, ParseState::p_hasWindowFuncs, ParseState::p_is_insert, ParseState::p_joinlist, ParseState::p_locking_clause, ParseState::p_rtable, ParseState::p_rteperminfos, ParseState::p_windowdefs, parseCheckAggregates(), parser_errposition(), Query::rtable, Query::sortClause, SelectStmt::sortClause, stmt, Query::targetList, SelectStmt::targetList, transformAssignmentIndirection(), transformDistinctClause(), transformDistinctOnClause(), transformExpr(), transformFromClause(), transformGroupClause(), transformLimitClause(), transformLockingClause(), transformSortClause(), transformTargetList(), transformWhereClause(), transformWindowDefinitions(), SelectStmt::whereClause, Query::windowClause, and SelectStmt::windowClause.

Referenced by transformStmt().

◆ transformReturningList()

List* transformReturningList ( ParseState pstate,
List returningList,
ParseExprKind  exprKind 
)

Definition at line 2560 of file analyze.c.

2562 {
2563  List *rlist;
2564  int save_next_resno;
2565 
2566  if (returningList == NIL)
2567  return NIL; /* nothing to do */
2568 
2569  /*
2570  * We need to assign resnos starting at one in the RETURNING list. Save
2571  * and restore the main tlist's value of p_next_resno, just in case
2572  * someone looks at it later (probably won't happen).
2573  */
2574  save_next_resno = pstate->p_next_resno;
2575  pstate->p_next_resno = 1;
2576 
2577  /* transform RETURNING identically to a SELECT targetlist */
2578  rlist = transformTargetList(pstate, returningList, exprKind);
2579 
2580  /*
2581  * Complain if the nonempty tlist expanded to nothing (which is possible
2582  * if it contains only a star-expansion of a zero-column table). If we
2583  * allow this, the parsed Query will look like it didn't have RETURNING,
2584  * with results that would probably surprise the user.
2585  */
2586  if (rlist == NIL)
2587  ereport(ERROR,
2588  (errcode(ERRCODE_SYNTAX_ERROR),
2589  errmsg("RETURNING must have at least one column"),
2590  parser_errposition(pstate,
2591  exprLocation(linitial(returningList)))));
2592 
2593  /* mark column origins */
2594  markTargetListOrigins(pstate, rlist);
2595 
2596  /* resolve any still-unresolved output columns as being type text */
2597  if (pstate->p_resolve_unknowns)
2598  resolveTargetListUnknowns(pstate, rlist);
2599 
2600  /* restore state */
2601  pstate->p_next_resno = save_next_resno;
2602 
2603  return rlist;
2604 }
void resolveTargetListUnknowns(ParseState *pstate, List *targetlist)
Definition: parse_target.c:288
void markTargetListOrigins(ParseState *pstate, List *targetlist)
Definition: parse_target.c:318
int p_next_resno
Definition: parse_node.h:212

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

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

◆ transformReturnStmt()

static Query * transformReturnStmt ( ParseState pstate,
ReturnStmt stmt 
)
static

Definition at line 2388 of file analyze.c.

2389 {
2390  Query *qry = makeNode(Query);
2391 
2392  qry->commandType = CMD_SELECT;
2393  qry->isReturn = true;
2394 
2396  1, NULL, false));
2397 
2398  if (pstate->p_resolve_unknowns)
2399  resolveTargetListUnknowns(pstate, qry->targetList);
2400  qry->rtable = pstate->p_rtable;
2401  qry->rteperminfos = pstate->p_rteperminfos;
2402  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
2403  qry->hasSubLinks = pstate->p_hasSubLinks;
2404  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
2405  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2406  qry->hasAggs = pstate->p_hasAggs;
2407 
2408  assign_query_collations(pstate, qry);
2409 
2410  return qry;
2411 }

References assign_query_collations(), CMD_SELECT, Query::commandType, EXPR_KIND_SELECT_TARGET, Query::jointree, list_make1, makeFromExpr(), makeNode, makeTargetEntry(), ParseState::p_hasAggs, ParseState::p_hasSubLinks, ParseState::p_hasTargetSRFs, ParseState::p_hasWindowFuncs, ParseState::p_joinlist, ParseState::p_resolve_unknowns, ParseState::p_rtable, ParseState::p_rteperminfos, resolveTargetListUnknowns(), Query::rtable, stmt, Query::targetList, and transformExpr().

Referenced by transformStmt().

◆ transformSelectStmt()

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

Definition at line 1337 of file analyze.c.

1338 {
1339  Query *qry = makeNode(Query);
1340  Node *qual;
1341  ListCell *l;
1342 
1343  qry->commandType = CMD_SELECT;
1344 
1345  /* process the WITH clause independently of all else */
1346  if (stmt->withClause)
1347  {
1348  qry->hasRecursive = stmt->withClause->recursive;
1349  qry->cteList = transformWithClause(pstate, stmt->withClause);
1350  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1351  }
1352 
1353  /* Complain if we get called from someplace where INTO is not allowed */
1354  if (stmt->intoClause)
1355  ereport(ERROR,
1356  (errcode(ERRCODE_SYNTAX_ERROR),
1357  errmsg("SELECT ... INTO is not allowed here"),
1358  parser_errposition(pstate,
1359  exprLocation((Node *) stmt->intoClause))));
1360 
1361  /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
1362  pstate->p_locking_clause = stmt->lockingClause;
1363 
1364  /* make WINDOW info available for window functions, too */
1365  pstate->p_windowdefs = stmt->windowClause;
1366 
1367  /* process the FROM clause */
1368  transformFromClause(pstate, stmt->fromClause);
1369 
1370  /* transform targetlist */
1371  qry->targetList = transformTargetList(pstate, stmt->targetList,
1373 
1374  /* mark column origins */
1375  markTargetListOrigins(pstate, qry->targetList);
1376 
1377  /* transform WHERE */
1378  qual = transformWhereClause(pstate, stmt->whereClause,
1379  EXPR_KIND_WHERE, "WHERE");
1380 
1381  /* initial processing of HAVING clause is much like WHERE clause */
1382  qry->havingQual = transformWhereClause(pstate, stmt->havingClause,
1383  EXPR_KIND_HAVING, "HAVING");
1384 
1385  /*
1386  * Transform sorting/grouping stuff. Do ORDER BY first because both
1387  * transformGroupClause and transformDistinctClause need the results. Note
1388  * that these functions can also change the targetList, so it's passed to
1389  * them by reference.
1390  */
1391  qry->sortClause = transformSortClause(pstate,
1392  stmt->sortClause,
1393  &qry->targetList,
1395  false /* allow SQL92 rules */ );
1396 
1397  qry->groupClause = transformGroupClause(pstate,
1398  stmt->groupClause,
1399  &qry->groupingSets,
1400  &qry->targetList,
1401  qry->sortClause,
1403  false /* allow SQL92 rules */ );
1404  qry->groupDistinct = stmt->groupDistinct;
1405 
1406  if (stmt->distinctClause == NIL)
1407  {
1408  qry->distinctClause = NIL;
1409  qry->hasDistinctOn = false;
1410  }
1411  else if (linitial(stmt->distinctClause) == NULL)
1412  {
1413  /* We had SELECT DISTINCT */
1415  &qry->targetList,
1416  qry->sortClause,
1417  false);
1418  qry->hasDistinctOn = false;
1419  }
1420  else
1421  {
1422  /* We had SELECT DISTINCT ON */
1424  stmt->distinctClause,
1425  &qry->targetList,
1426  qry->sortClause);
1427  qry->hasDistinctOn = true;
1428  }
1429 
1430  /* transform LIMIT */
1431  qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
1432  EXPR_KIND_OFFSET, "OFFSET",
1433  stmt->limitOption);
1434  qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
1435  EXPR_KIND_LIMIT, "LIMIT",
1436  stmt->limitOption);
1437  qry->limitOption = stmt->limitOption;
1438 
1439  /* transform window clauses after we have seen all window functions */
1441  pstate->p_windowdefs,
1442  &qry->targetList);
1443 
1444  /* resolve any still-unresolved output columns as being type text */
1445  if (pstate->p_resolve_unknowns)
1446  resolveTargetListUnknowns(pstate, qry->targetList);
1447 
1448  qry->rtable = pstate->p_rtable;
1449  qry->rteperminfos = pstate->p_rteperminfos;
1450  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
1451 
1452  qry->hasSubLinks = pstate->p_hasSubLinks;
1453  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
1454  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
1455  qry->hasAggs = pstate->p_hasAggs;
1456 
1457  foreach(l, stmt->lockingClause)
1458  {
1459  transformLockingClause(pstate, qry,
1460  (LockingClause *) lfirst(l), false);
1461  }
1462 
1463  assign_query_collations(pstate, qry);
1464 
1465  /* this must be done after collations, for reliable comparison of exprs */
1466  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
1467  parseCheckAggregates(pstate, qry);
1468 
1469  return qry;
1470 }
bool groupDistinct
Definition: parsenodes.h:201

References assign_query_collations(), CMD_SELECT, Query::commandType, Query::cteList, Query::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(), Query::groupClause, Query::groupDistinct, Query::groupingSets, Query::havingQual, Query::jointree, lfirst, Query::limitCount, Query::limitOffset, Query::limitOption, linitial, 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_rteperminfos, ParseState::p_windowdefs, parseCheckAggregates(), parser_errposition(), resolveTargetListUnknowns(), Query::rtable, Query::sortClause, stmt, Query::targetList, transformDistinctClause(), transformDistinctOnClause(), transformFromClause(), transformGroupClause(), transformLimitClause(), transformLockingClause(), transformSortClause(), transformTargetList(), transformWhereClause(), transformWindowDefinitions(), transformWithClause(), and Query::windowClause.

Referenced by transformStmt().

◆ transformSetOperationStmt()

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

Definition at line 1699 of file analyze.c.

1700 {
1701  Query *qry = makeNode(Query);
1702  SelectStmt *leftmostSelect;
1703  int leftmostRTI;
1704  Query *leftmostQuery;
1705  SetOperationStmt *sostmt;
1706  List *sortClause;
1707  Node *limitOffset;
1708  Node *limitCount;
1709  List *lockingClause;
1710  WithClause *withClause;
1711  Node *node;
1712  ListCell *left_tlist,
1713  *lct,
1714  *lcm,
1715  *lcc,
1716  *l;
1717  List *targetvars,
1718  *targetnames,
1719  *sv_namespace;
1720  int sv_rtable_length;
1721  ParseNamespaceItem *jnsitem;
1722  ParseNamespaceColumn *sortnscolumns;
1723  int sortcolindex;
1724  int tllen;
1725 
1726  qry->commandType = CMD_SELECT;
1727 
1728  /*
1729  * Find leftmost leaf SelectStmt. We currently only need to do this in
1730  * order to deliver a suitable error message if there's an INTO clause
1731  * there, implying the set-op tree is in a context that doesn't allow
1732  * INTO. (transformSetOperationTree would throw error anyway, but it
1733  * seems worth the trouble to throw a different error for non-leftmost
1734  * INTO, so we produce that error in transformSetOperationTree.)
1735  */
1736  leftmostSelect = stmt->larg;
1737  while (leftmostSelect && leftmostSelect->op != SETOP_NONE)
1738  leftmostSelect = leftmostSelect->larg;
1739  Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
1740  leftmostSelect->larg == NULL);
1741  if (leftmostSelect->intoClause)
1742  ereport(ERROR,
1743  (errcode(ERRCODE_SYNTAX_ERROR),
1744  errmsg("SELECT ... INTO is not allowed here"),
1745  parser_errposition(pstate,
1746  exprLocation((Node *) leftmostSelect->intoClause))));
1747 
1748  /*
1749  * We need to extract ORDER BY and other top-level clauses here and not
1750  * let transformSetOperationTree() see them --- else it'll just recurse
1751  * right back here!
1752  */
1753  sortClause = stmt->sortClause;
1754  limitOffset = stmt->limitOffset;
1755  limitCount = stmt->limitCount;
1756  lockingClause = stmt->lockingClause;
1757  withClause = stmt->withClause;
1758 
1759  stmt->sortClause = NIL;
1760  stmt->limitOffset = NULL;
1761  stmt->limitCount = NULL;
1762  stmt->lockingClause = NIL;
1763  stmt->withClause = NULL;
1764 
1765  /* We don't support FOR UPDATE/SHARE with set ops at the moment. */
1766  if (lockingClause)
1767  ereport(ERROR,
1768  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1769  /*------
1770  translator: %s is a SQL row locking clause such as FOR UPDATE */
1771  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
1773  linitial(lockingClause))->strength))));
1774 
1775  /* Process the WITH clause independently of all else */
1776  if (withClause)
1777  {
1778  qry->hasRecursive = withClause->recursive;
1779  qry->cteList = transformWithClause(pstate, withClause);
1780  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1781  }
1782 
1783  /*
1784  * Recursively transform the components of the tree.
1785  */
1786  sostmt = castNode(SetOperationStmt,
1787  transformSetOperationTree(pstate, stmt, true, NULL));
1788  Assert(sostmt);
1789  qry->setOperations = (Node *) sostmt;
1790 
1791  /*
1792  * Re-find leftmost SELECT (now it's a sub-query in rangetable)
1793  */
1794  node = sostmt->larg;
1795  while (node && IsA(node, SetOperationStmt))
1796  node = ((SetOperationStmt *) node)->larg;
1797  Assert(node && IsA(node, RangeTblRef));
1798  leftmostRTI = ((RangeTblRef *) node)->rtindex;
1799  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
1800  Assert(leftmostQuery != NULL);
1801 
1802  /*
1803  * Generate dummy targetlist for outer query using column names of
1804  * leftmost select and common datatypes/collations of topmost set
1805  * operation. Also make lists of the dummy vars and their names for use
1806  * in parsing ORDER BY.
1807  *
1808  * Note: we use leftmostRTI as the varno of the dummy variables. It
1809  * shouldn't matter too much which RT index they have, as long as they
1810  * have one that corresponds to a real RT entry; else funny things may
1811  * happen when the tree is mashed by rule rewriting.
1812  */
1813  qry->targetList = NIL;
1814  targetvars = NIL;
1815  targetnames = NIL;
1816  sortnscolumns = (ParseNamespaceColumn *)
1817  palloc0(list_length(sostmt->colTypes) * sizeof(ParseNamespaceColumn));
1818  sortcolindex = 0;
1819 
1820  forfour(lct, sostmt->colTypes,
1821  lcm, sostmt->colTypmods,
1822  lcc, sostmt->colCollations,
1823  left_tlist, leftmostQuery->targetList)
1824  {
1825  Oid colType = lfirst_oid(lct);
1826  int32 colTypmod = lfirst_int(lcm);
1827  Oid colCollation = lfirst_oid(lcc);
1828  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
1829  char *colName;
1830  TargetEntry *tle;
1831  Var *var;
1832 
1833  Assert(!lefttle->resjunk);
1834  colName = pstrdup(lefttle->resname);
1835  var = makeVar(leftmostRTI,
1836  lefttle->resno,
1837  colType,
1838  colTypmod,
1839  colCollation,
1840  0);
1841  var->location = exprLocation((Node *) lefttle->expr);
1842  tle = makeTargetEntry((Expr *) var,
1843  (AttrNumber) pstate->p_next_resno++,
1844  colName,
1845  false);
1846  qry->targetList = lappend(qry->targetList, tle);
1847  targetvars = lappend(targetvars, var);
1848  targetnames = lappend(targetnames, makeString(colName));
1849  sortnscolumns[sortcolindex].p_varno = leftmostRTI;
1850  sortnscolumns[sortcolindex].p_varattno = lefttle->resno;
1851  sortnscolumns[sortcolindex].p_vartype = colType;
1852  sortnscolumns[sortcolindex].p_vartypmod = colTypmod;
1853  sortnscolumns[sortcolindex].p_varcollid = colCollation;
1854  sortnscolumns[sortcolindex].p_varnosyn = leftmostRTI;
1855  sortnscolumns[sortcolindex].p_varattnosyn = lefttle->resno;
1856  sortcolindex++;
1857  }
1858 
1859  /*
1860  * As a first step towards supporting sort clauses that are expressions
1861  * using the output columns, generate a namespace entry that makes the
1862  * output columns visible. A Join RTE node is handy for this, since we
1863  * can easily control the Vars generated upon matches.
1864  *
1865  * Note: we don't yet do anything useful with such cases, but at least
1866  * "ORDER BY upper(foo)" will draw the right error message rather than
1867  * "foo not found".
1868  */
1869  sv_rtable_length = list_length(pstate->p_rtable);
1870 
1871  jnsitem = addRangeTableEntryForJoin(pstate,
1872  targetnames,
1873  sortnscolumns,
1874  JOIN_INNER,
1875  0,
1876  targetvars,
1877  NIL,
1878  NIL,
1879  NULL,
1880  NULL,
1881  false);
1882 
1883  sv_namespace = pstate->p_namespace;
1884  pstate->p_namespace = NIL;
1885 
1886  /* add jnsitem to column namespace only */
1887  addNSItemToQuery(pstate, jnsitem, false, false, true);
1888 
1889  /*
1890  * For now, we don't support resjunk sort clauses on the output of a
1891  * setOperation tree --- you can only use the SQL92-spec options of
1892  * selecting an output column by name or number. Enforce by checking that
1893  * transformSortClause doesn't add any items to tlist. Note, if changing
1894  * this, add_setop_child_rel_equivalences() will need to be updated.
1895  */
1896  tllen = list_length(qry->targetList);
1897 
1898  qry->sortClause = transformSortClause(pstate,
1899  sortClause,
1900  &qry->targetList,
1902  false /* allow SQL92 rules */ );
1903 
1904  /* restore namespace, remove join RTE from rtable */
1905  pstate->p_namespace = sv_namespace;
1906  pstate->p_rtable = list_truncate(pstate->p_rtable, sv_rtable_length);
1907 
1908  if (tllen != list_length(qry->targetList))
1909  ereport(ERROR,
1910  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1911  errmsg("invalid UNION/INTERSECT/EXCEPT ORDER BY clause"),
1912  errdetail("Only result column names can be used, not expressions or functions."),
1913  errhint("Add the expression/function to every SELECT, or move the UNION into a FROM clause."),
1914  parser_errposition(pstate,
1915  exprLocation(list_nth(qry->targetList, tllen)))));
1916 
1917  qry->limitOffset = transformLimitClause(pstate, limitOffset,
1918  EXPR_KIND_OFFSET, "OFFSET",
1919  stmt->limitOption);
1920  qry->limitCount = transformLimitClause(pstate, limitCount,
1921  EXPR_KIND_LIMIT, "LIMIT",
1922  stmt->limitOption);
1923  qry->limitOption = stmt->limitOption;
1924 
1925  qry->rtable = pstate->p_rtable;
1926  qry->rteperminfos = pstate->p_rteperminfos;
1927  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
1928 
1929  qry->hasSubLinks = pstate->p_hasSubLinks;
1930  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
1931  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
1932  qry->hasAggs = pstate->p_hasAggs;
1933 
1934  foreach(l, lockingClause)
1935  {
1936  transformLockingClause(pstate, qry,
1937  (LockingClause *) lfirst(l), false);
1938  }
1939 
1940  assign_query_collations(pstate, qry);
1941 
1942  /* this must be done after collations, for reliable comparison of exprs */
1943  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
1944  parseCheckAggregates(pstate, qry);
1945 
1946  return qry;
1947 }
List * list_truncate(List *list, int new_size)
Definition: list.c:631
void * palloc0(Size size)
Definition: mcxt.c:1346
@ JOIN_INNER
Definition: nodes.h:293
struct ParseNamespaceColumn ParseNamespaceColumn
Definition: parse_node.h:25
ParseNamespaceItem * addRangeTableEntryForJoin(ParseState *pstate, List *colnames, ParseNamespaceColumn *nscolumns, JoinType jointype, int nummergedcols, List *aliasvars, List *leftcols, List *rightcols, Alias *join_using_alias, Alias *alias, bool inFromCl)
static Node * transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, bool isTopLevel, List **targetlist)
Definition: analyze.c:2003
#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4)
Definition: pg_list.h:575
#define lfirst_oid(lc)
Definition: pg_list.h:174
AttrNumber p_varattno
Definition: parse_node.h:322
AttrNumber p_varattnosyn
Definition: parse_node.h:327
struct SelectStmt * larg
Definition: parsenodes.h:2163
SetOperation op
Definition: parsenodes.h:2161
AttrNumber resno
Definition: primnodes.h:2194
bool recursive
Definition: parsenodes.h:1599

References addNSItemToQuery(), addRangeTableEntryForJoin(), Assert, assign_query_collations(), castNode, CMD_SELECT, 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::havingQual, SelectStmt::intoClause, IsA, JOIN_INNER, Query::jointree, lappend(), SelectStmt::larg, SetOperationStmt::larg, LCS_asString(), lfirst, lfirst_int, lfirst_oid, Query::limitCount, Query::limitOffset, Query::limitOption, linitial, list_length(), list_nth(), list_truncate(), Var::location, 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, ParseState::p_rteperminfos, 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::resno, rt_fetch, Query::rtable, SETOP_NONE, Query::setOperations, Query::sortClause, stmt, Query::targetList, transformLimitClause(), transformLockingClause(), transformSetOperationTree(), transformSortClause(), and transformWithClause().

Referenced by transformStmt().

◆ transformSetOperationTree()

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

Definition at line 2003 of file analyze.c.

2005 {
2006  bool isLeaf;
2007 
2008  Assert(stmt && IsA(stmt, SelectStmt));
2009 
2010  /* Guard against stack overflow due to overly complex set-expressions */
2012 
2013  /*
2014  * Validity-check both leaf and internal SELECTs for disallowed ops.
2015  */
2016  if (stmt->intoClause)
2017  ereport(ERROR,
2018  (errcode(ERRCODE_SYNTAX_ERROR),
2019  errmsg("INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"),
2020  parser_errposition(pstate,
2021  exprLocation((Node *) stmt->intoClause))));
2022 
2023  /* We don't support FOR UPDATE/SHARE with set ops at the moment. */
2024  if (stmt->lockingClause)
2025  ereport(ERROR,
2026  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2027  /*------
2028  translator: %s is a SQL row locking clause such as FOR UPDATE */
2029  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
2031  linitial(stmt->lockingClause))->strength))));
2032 
2033  /*
2034  * If an internal node of a set-op tree has ORDER BY, LIMIT, FOR UPDATE,
2035  * or WITH clauses attached, we need to treat it like a leaf node to
2036  * generate an independent sub-Query tree. Otherwise, it can be
2037  * represented by a SetOperationStmt node underneath the parent Query.
2038  */
2039  if (stmt->op == SETOP_NONE)
2040  {
2041  Assert(stmt->larg == NULL && stmt->rarg == NULL);
2042  isLeaf = true;
2043  }
2044  else
2045  {
2046  Assert(stmt->larg != NULL && stmt->rarg != NULL);
2047  if (stmt->sortClause || stmt->limitOffset || stmt->limitCount ||
2048  stmt->lockingClause || stmt->withClause)
2049  isLeaf = true;
2050  else
2051  isLeaf = false;
2052  }
2053 
2054  if (isLeaf)
2055  {
2056  /* Process leaf SELECT */
2057  Query *selectQuery;
2058  char selectName[32];
2059  ParseNamespaceItem *nsitem;
2060  RangeTblRef *rtr;
2061  ListCell *tl;
2062 
2063  /*
2064  * Transform SelectStmt into a Query.
2065  *
2066  * This works the same as SELECT transformation normally would, except
2067  * that we prevent resolving unknown-type outputs as TEXT. This does
2068  * not change the subquery's semantics since if the column type
2069  * matters semantically, it would have been resolved to something else
2070  * anyway. Doing this lets us resolve such outputs using
2071  * select_common_type(), below.
2072  *
2073  * Note: previously transformed sub-queries don't affect the parsing
2074  * of this sub-query, because they are not in the toplevel pstate's
2075  * namespace list.
2076  */
2077  selectQuery = parse_sub_analyze((Node *) stmt, pstate,
2078  NULL, false, false);
2079 
2080  /*
2081  * Check for bogus references to Vars on the current query level (but
2082  * upper-level references are okay). Normally this can't happen
2083  * because the namespace will be empty, but it could happen if we are
2084  * inside a rule.
2085  */
2086  if (pstate->p_namespace)
2087  {
2088  if (contain_vars_of_level((Node *) selectQuery, 1))
2089  ereport(ERROR,
2090  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2091  errmsg("UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level"),
2092  parser_errposition(pstate,
2093  locate_var_of_level((Node *) selectQuery, 1))));
2094  }
2095 
2096  /*
2097  * Extract a list of the non-junk TLEs for upper-level processing.
2098  */
2099  if (targetlist)
2100  {
2101  *targetlist = NIL;
2102  foreach(tl, selectQuery->targetList)
2103  {
2104  TargetEntry *tle = (TargetEntry *) lfirst(tl);
2105 
2106  if (!tle->resjunk)
2107  *targetlist = lappend(*targetlist, tle);
2108  }
2109  }
2110 
2111  /*
2112  * Make the leaf query be a subquery in the top-level rangetable.
2113  */
2114  snprintf(selectName, sizeof(selectName), "*SELECT* %d",
2115  list_length(pstate->p_rtable) + 1);
2116  nsitem = addRangeTableEntryForSubquery(pstate,
2117  selectQuery,
2118  makeAlias(selectName, NIL),
2119  false,
2120  false);
2121 
2122  /*
2123  * Return a RangeTblRef to replace the SelectStmt in the set-op tree.
2124  */
2125  rtr = makeNode(RangeTblRef);
2126  rtr->rtindex = nsitem->p_rtindex;
2127  return (Node *) rtr;
2128  }
2129  else
2130  {
2131  /* Process an internal node (set operation node) */
2133  List *ltargetlist;
2134  List *rtargetlist;
2135  ListCell *ltl;
2136  ListCell *rtl;
2137  const char *context;
2138  bool recursive = (pstate->p_parent_cte &&
2139  pstate->p_parent_cte->cterecursive);
2140 
2141  context = (stmt->op == SETOP_UNION ? "UNION" :
2142  (stmt->op == SETOP_INTERSECT ? "INTERSECT" :
2143  "EXCEPT"));
2144 
2145  op->op = stmt->op;
2146  op->all = stmt->all;
2147 
2148  /*
2149  * Recursively transform the left child node.
2150  */
2151  op->larg = transformSetOperationTree(pstate, stmt->larg,
2152  false,
2153  &ltargetlist);
2154 
2155  /*
2156  * If we are processing a recursive union query, now is the time to
2157  * examine the non-recursive term's output columns and mark the
2158  * containing CTE as having those result columns. We should do this
2159  * only at the topmost setop of the CTE, of course.
2160  */
2161  if (isTopLevel && recursive)
2162  determineRecursiveColTypes(pstate, op->larg, ltargetlist);
2163 
2164  /*
2165  * Recursively transform the right child node.
2166  */
2167  op->rarg = transformSetOperationTree(pstate, stmt->rarg,
2168  false,
2169  &rtargetlist);
2170 
2171  /*
2172  * Verify that the two children have the same number of non-junk
2173  * columns, and determine the types of the merged output columns.
2174  */
2175  if (list_length(ltargetlist) != list_length(rtargetlist))
2176  ereport(ERROR,
2177  (errcode(ERRCODE_SYNTAX_ERROR),
2178  errmsg("each %s query must have the same number of columns",
2179  context),
2180  parser_errposition(pstate,
2181  exprLocation((Node *) rtargetlist))));
2182 
2183  if (targetlist)
2184  *targetlist = NIL;
2185  op->colTypes = NIL;
2186  op->colTypmods = NIL;
2187  op->colCollations = NIL;
2188  op->groupClauses = NIL;
2189  forboth(ltl, ltargetlist, rtl, rtargetlist)
2190  {
2191  TargetEntry *ltle = (TargetEntry *) lfirst(ltl);
2192  TargetEntry *rtle = (TargetEntry *) lfirst(rtl);
2193  Node *lcolnode = (Node *) ltle->expr;
2194  Node *rcolnode = (Node *) rtle->expr;
2195  Oid lcoltype = exprType(lcolnode);
2196  Oid rcoltype = exprType(rcolnode);
2197  Node *bestexpr;
2198  int bestlocation;
2199  Oid rescoltype;
2200  int32 rescoltypmod;
2201  Oid rescolcoll;
2202 
2203  /* select common type, same as CASE et al */
2204  rescoltype = select_common_type(pstate,
2205  list_make2(lcolnode, rcolnode),
2206  context,
2207  &bestexpr);
2208  bestlocation = exprLocation(bestexpr);
2209 
2210  /*
2211  * Verify the coercions are actually possible. If not, we'd fail
2212  * later anyway, but we want to fail now while we have sufficient
2213  * context to produce an error cursor position.
2214  *
2215  * For all non-UNKNOWN-type cases, we verify coercibility but we
2216  * don't modify the child's expression, for fear of changing the
2217  * child query's semantics.
2218  *
2219  * If a child expression is an UNKNOWN-type Const or Param, we
2220  * want to replace it with the coerced expression. This can only
2221  * happen when the child is a leaf set-op node. It's safe to
2222  * replace the expression because if the child query's semantics
2223  * depended on the type of this output column, it'd have already
2224  * coerced the UNKNOWN to something else. We want to do this
2225  * because (a) we want to verify that a Const is valid for the
2226  * target type, or resolve the actual type of an UNKNOWN Param,
2227  * and (b) we want to avoid unnecessary discrepancies between the
2228  * output type of the child query and the resolved target type.
2229  * Such a discrepancy would disable optimization in the planner.
2230  *
2231  * If it's some other UNKNOWN-type node, eg a Var, we do nothing
2232  * (knowing that coerce_to_common_type would fail). The planner
2233  * is sometimes able to fold an UNKNOWN Var to a constant before
2234  * it has to coerce the type, so failing now would just break
2235  * cases that might work.
2236  */
2237  if (lcoltype != UNKNOWNOID)
2238  lcolnode = coerce_to_common_type(pstate, lcolnode,
2239  rescoltype, context);
2240  else if (IsA(lcolnode, Const) ||
2241  IsA(lcolnode, Param))
2242  {
2243  lcolnode = coerce_to_common_type(pstate, lcolnode,
2244  rescoltype, context);
2245  ltle->expr = (Expr *) lcolnode;
2246  }
2247 
2248  if (rcoltype != UNKNOWNOID)
2249  rcolnode = coerce_to_common_type(pstate, rcolnode,
2250  rescoltype, context);
2251  else if (IsA(rcolnode, Const) ||
2252  IsA(rcolnode, Param))
2253  {
2254  rcolnode = coerce_to_common_type(pstate, rcolnode,
2255  rescoltype, context);
2256  rtle->expr = (Expr *) rcolnode;
2257  }
2258 
2259  rescoltypmod = select_common_typmod(pstate,
2260  list_make2(lcolnode, rcolnode),
2261  rescoltype);
2262 
2263  /*
2264  * Select common collation. A common collation is required for
2265  * all set operators except UNION ALL; see SQL:2008 7.13 <query
2266  * expression> Syntax Rule 15c. (If we fail to identify a common
2267  * collation for a UNION ALL column, the colCollations element
2268  * will be set to InvalidOid, which may result in a runtime error
2269  * if something at a higher query level wants to use the column's
2270  * collation.)
2271  */
2272  rescolcoll = select_common_collation(pstate,
2273  list_make2(lcolnode, rcolnode),
2274  (op->op == SETOP_UNION && op->all));
2275 
2276  /* emit results */
2277  op->colTypes = lappend_oid(op->colTypes, rescoltype);
2278  op->colTypmods = lappend_int(op->colTypmods, rescoltypmod);
2279  op->colCollations = lappend_oid(op->colCollations, rescolcoll);
2280 
2281  /*
2282  * For all cases except UNION ALL, identify the grouping operators
2283  * (and, if available, sorting operators) that will be used to
2284  * eliminate duplicates.
2285  */
2286  if (op->op != SETOP_UNION || !op->all)
2287  {
2288  ParseCallbackState pcbstate;
2289 
2290  setup_parser_errposition_callback(&pcbstate, pstate,
2291  bestlocation);
2292 
2293  /*
2294  * If it's a recursive union, we need to require hashing
2295  * support.
2296  */
2297  op->groupClauses = lappend(op->groupClauses,
2298  makeSortGroupClauseForSetOp(rescoltype, recursive));
2299 
2301  }
2302 
2303  /*
2304  * Construct a dummy tlist entry to return. We use a SetToDefault
2305  * node for the expression, since it carries exactly the fields
2306  * needed, but any other expression node type would do as well.
2307  */
2308  if (targetlist)
2309  {
2310  SetToDefault *rescolnode = makeNode(SetToDefault);
2311  TargetEntry *restle;
2312 
2313  rescolnode->typeId = rescoltype;
2314  rescolnode->typeMod = rescoltypmod;
2315  rescolnode->collation = rescolcoll;
2316  rescolnode->location = bestlocation;
2317  restle = makeTargetEntry((Expr *) rescolnode,
2318  0, /* no need to set resno */
2319  NULL,
2320  false);
2321  *targetlist = lappend(*targetlist, restle);
2322  }
2323  }
2324 
2325  return (Node *) op;
2326  }
2327 }
Node * coerce_to_common_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *context)
int32 select_common_typmod(ParseState *pstate, List *exprs, Oid common_type)
Oid select_common_type(ParseState *pstate, List *exprs, const char *context, Node **which_expr)
Oid select_common_collation(ParseState *pstate, List *exprs, bool none_ok)
void cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
Definition: parse_node.c:156
void setup_parser_errposition_callback(ParseCallbackState *pcbstate, ParseState *pstate, int location)
Definition: parse_node.c:140
@ SETOP_INTERSECT
Definition: parsenodes.h:2115
@ SETOP_UNION
Definition: parsenodes.h:2114
Query * parse_sub_analyze(Node *parseTree, ParseState *parentParseState, CommonTableExpr *parentCTE, bool locked_from_parent, bool resolve_unknowns)
Definition: analyze.c:221
static void determineRecursiveColTypes(ParseState *pstate, Node *larg, List *nrtargetlist)
Definition: analyze.c:2334
SortGroupClause * makeSortGroupClauseForSetOp(Oid rescoltype, bool require_hash)
Definition: analyze.c:1956
#define list_make2(x1, x2)
Definition: pg_list.h:214
#define snprintf
Definition: port.h:238
void check_stack_depth(void)
Definition: postgres.c:3531
tree context
Definition: radixtree.h:1833
SetOperation op
Definition: parsenodes.h:2191
ParseLoc location
Definition: primnodes.h:2080
int locate_var_of_level(Node *node, int levelsup)
Definition: var.c:509

References addRangeTableEntryForSubquery(), SetOperationStmt::all, Assert, cancel_parser_errposition_callback(), check_stack_depth(), coerce_to_common_type(), contain_vars_of_level(), context, determineRecursiveColTypes(), ereport, errcode(), errmsg(), ERROR, TargetEntry::expr, exprLocation(), exprType(), forboth, IsA, lappend(), lappend_int(), lappend_oid(), SetOperationStmt::larg, LCS_asString(), lfirst, linitial, list_length(), list_make2, locate_var_of_level(), SetToDefault::location, makeAlias(), makeNode, makeSortGroupClauseForSetOp(), makeTargetEntry(), NIL, SetOperationStmt::op, ParseState::p_namespace, ParseState::p_parent_cte, ParseState::p_rtable, ParseNamespaceItem::p_rtindex, parse_sub_analyze(), parser_errposition(), SetOperationStmt::rarg, RangeTblRef::rtindex, select_common_collation(), select_common_type(), select_common_typmod(), SETOP_INTERSECT, SETOP_NONE, SETOP_UNION, setup_parser_errposition_callback(), snprintf, stmt, Query::targetList, and SetToDefault::typeId.

Referenced by transformSetOperationStmt().

◆ transformStmt()

Query* transformStmt ( ParseState pstate,
Node parseTree 
)

Definition at line 311 of file analyze.c.

312 {
313  Query *result;
314 
315  /*
316  * We apply RAW_EXPRESSION_COVERAGE_TEST testing to basic DML statements;
317  * we can't just run it on everything because raw_expression_tree_walker()
318  * doesn't claim to handle utility statements.
319  */
320 #ifdef RAW_EXPRESSION_COVERAGE_TEST
321  switch (nodeTag(parseTree))
322  {
323  case T_SelectStmt:
324  case T_InsertStmt:
325  case T_UpdateStmt:
326  case T_DeleteStmt:
327  case T_MergeStmt:
328  (void) test_raw_expression_coverage(parseTree, NULL);
329  break;
330  default:
331  break;
332  }
333 #endif /* RAW_EXPRESSION_COVERAGE_TEST */
334 
335  /*
336  * Caution: when changing the set of statement types that have non-default
337  * processing here, see also stmt_requires_parse_analysis() and
338  * analyze_requires_snapshot().
339  */
340  switch (nodeTag(parseTree))
341  {
342  /*
343  * Optimizable statements
344  */
345  case T_InsertStmt:
346  result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
347  break;
348 
349  case T_DeleteStmt:
350  result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
351  break;
352 
353  case T_UpdateStmt:
354  result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
355  break;
356 
357  case T_MergeStmt:
358  result = transformMergeStmt(pstate, (MergeStmt *) parseTree);
359  break;
360 
361  case T_SelectStmt:
362  {
363  SelectStmt *n = (SelectStmt *) parseTree;
364 
365  if (n->valuesLists)
366  result = transformValuesClause(pstate, n);
367  else if (n->op == SETOP_NONE)
368  result = transformSelectStmt(pstate, n);
369  else
370  result = transformSetOperationStmt(pstate, n);
371  }
372  break;
373 
374  case T_ReturnStmt:
375  result = transformReturnStmt(pstate, (ReturnStmt *) parseTree);
376  break;
377 
378  case T_PLAssignStmt:
379  result = transformPLAssignStmt(pstate,
380  (PLAssignStmt *) parseTree);
381  break;
382 
383  /*
384  * Special cases
385  */
386  case T_DeclareCursorStmt:
387  result = transformDeclareCursorStmt(pstate,
388  (DeclareCursorStmt *) parseTree);
389  break;
390 
391  case T_ExplainStmt:
392  result = transformExplainStmt(pstate,
393  (ExplainStmt *) parseTree);
394  break;
395 
396  case T_CreateTableAsStmt:
397  result = transformCreateTableAsStmt(pstate,
398  (CreateTableAsStmt *) parseTree);
399  break;
400 
401  case T_CallStmt:
402  result = transformCallStmt(pstate,
403  (CallStmt *) parseTree);
404  break;
405 
406  default:
407 
408  /*
409  * other statements don't require any transformation; just return
410  * the original parsetree with a Query node plastered on top.
411  */
412  result = makeNode(Query);
413  result->commandType = CMD_UTILITY;
414  result->utilityStmt = (Node *) parseTree;
415  break;
416  }
417 
418  /* Mark as original query until we learn differently */
419  result->querySource = QSRC_ORIGINAL;
420  result->canSetTag = true;
421 
422  return result;
423 }
Query * transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
Definition: parse_merge.c:107
@ QSRC_ORIGINAL
Definition: parsenodes.h:36
static Query * transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
Definition: analyze.c:508
static Query * transformReturnStmt(ParseState *pstate, ReturnStmt *stmt)
Definition: analyze.c:2388
static Query * transformPLAssignStmt(ParseState *pstate, PLAssignStmt *stmt)
Definition: analyze.c:2619
static Query * transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
Definition: analyze.c:3013
static Query * transformCallStmt(ParseState *pstate, CallStmt *stmt)
Definition: analyze.c:3088
static Query * transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1699
static Query * transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
Definition: analyze.c:2419
static Query * transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1337
static Query * transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
Definition: analyze.c:2961
static Query * transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
Definition: analyze.c:2868
static Query * transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
Definition: analyze.c:580
static Query * transformValuesClause(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1480

References CMD_UTILITY, Query::commandType, makeNode, nodeTag, SelectStmt::op, QSRC_ORIGINAL, SETOP_NONE, transformCallStmt(), transformCreateTableAsStmt(), transformDeclareCursorStmt(), transformDeleteStmt(), transformExplainStmt(), transformInsertStmt(), transformMergeStmt(), transformPLAssignStmt(), transformReturnStmt(), transformSelectStmt(), transformSetOperationStmt(), transformUpdateStmt(), transformValuesClause(), Query::utilityStmt, and SelectStmt::valuesLists.

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

◆ transformTopLevelStmt()

Query* transformTopLevelStmt ( ParseState pstate,
RawStmt parseTree 
)

Definition at line 248 of file analyze.c.

249 {
250  Query *result;
251 
252  /* We're at top level, so allow SELECT INTO */
253  result = transformOptionalSelectInto(pstate, parseTree->stmt);
254 
255  result->stmt_location = parseTree->stmt_location;
256  result->stmt_len = parseTree->stmt_len;
257 
258  return result;
259 }
ParseLoc stmt_location
Definition: parsenodes.h:238
ParseLoc stmt_location
Definition: parsenodes.h:2026
ParseLoc stmt_len
Definition: parsenodes.h:2027

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

Referenced by inline_function(), parse_analyze_fixedparams(), parse_analyze_varparams(), and parse_analyze_withcb().

◆ transformUpdateStmt()

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

Definition at line 2419 of file analyze.c.

2420 {
2421  Query *qry = makeNode(Query);
2422  ParseNamespaceItem *nsitem;
2423  Node *qual;
2424 
2425  qry->commandType = CMD_UPDATE;
2426  pstate->p_is_insert = false;
2427 
2428  /* process the WITH clause independently of all else */
2429  if (stmt->withClause)
2430  {
2431  qry->hasRecursive = stmt->withClause->recursive;
2432  qry->cteList = transformWithClause(pstate, stmt->withClause);
2433  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
2434  }
2435 
2436  qry->resultRelation = setTargetTable(pstate, stmt->relation,
2437  stmt->relation->inh,
2438  true,
2439  ACL_UPDATE);
2440  nsitem = pstate->p_target_nsitem;
2441 
2442  /* subqueries in FROM cannot access the result relation */
2443  nsitem->p_lateral_only = true;
2444  nsitem->p_lateral_ok = false;
2445 
2446  /*
2447  * the FROM clause is non-standard SQL syntax. We used to be able to do
2448  * this with REPLACE in POSTQUEL so we keep the feature.
2449  */
2450  transformFromClause(pstate, stmt->fromClause);
2451 
2452  /* remaining clauses can reference the result relation normally */
2453  nsitem->p_lateral_only = false;
2454  nsitem->p_lateral_ok = true;
2455 
2456  qual = transformWhereClause(pstate, stmt->whereClause,
2457  EXPR_KIND_WHERE, "WHERE");
2458 
2459  qry->returningList = transformReturningList(pstate, stmt->returningList,
2461 
2462  /*
2463  * Now we are done with SELECT-like processing, and can get on with
2464  * transforming the target list to match the UPDATE target columns.
2465  */
2466  qry->targetList = transformUpdateTargetList(pstate, stmt->targetList);
2467 
2468  qry->rtable = pstate->p_rtable;
2469  qry->rteperminfos = pstate->p_rteperminfos;
2470  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2471 
2472  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2473  qry->hasSubLinks = pstate->p_hasSubLinks;
2474 
2475  assign_query_collations(pstate, qry);
2476 
2477  return qry;
2478 }
@ CMD_UPDATE
Definition: nodes.h:266

References ACL_UPDATE, assign_query_collations(), CMD_UPDATE, Query::commandType, Query::cteList, EXPR_KIND_RETURNING, EXPR_KIND_WHERE, 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_rteperminfos, ParseState::p_target_nsitem, Query::returningList, Query::rtable, setTargetTable(), stmt, Query::targetList, transformFromClause(), transformReturningList(), transformUpdateTargetList(), transformWhereClause(), and transformWithClause().

Referenced by transformStmt().

◆ transformUpdateTargetList()

List* transformUpdateTargetList ( ParseState pstate,
List origTlist 
)

Definition at line 2485 of file analyze.c.

2486 {
2487  List *tlist = NIL;
2488  RTEPermissionInfo *target_perminfo;
2489  ListCell *orig_tl;
2490  ListCell *tl;
2491 
2492  tlist = transformTargetList(pstate, origTlist,
2494 
2495  /* Prepare to assign non-conflicting resnos to resjunk attributes */
2498 
2499  /* Prepare non-junk columns for assignment to target table */
2500  target_perminfo = pstate->p_target_nsitem->p_perminfo;
2501  orig_tl = list_head(origTlist);
2502 
2503  foreach(tl, tlist)
2504  {
2505  TargetEntry *tle = (TargetEntry *) lfirst(tl);
2506  ResTarget *origTarget;
2507  int attrno;
2508 
2509  if (tle->resjunk)
2510  {
2511  /*
2512  * Resjunk nodes need no additional processing, but be sure they
2513  * have resnos that do not match any target columns; else rewriter
2514  * or planner might get confused. They don't need a resname
2515  * either.
2516  */
2517  tle->resno = (AttrNumber) pstate->p_next_resno++;
2518  tle->resname = NULL;
2519  continue;
2520  }
2521  if (orig_tl == NULL)
2522  elog(ERROR, "UPDATE target count mismatch --- internal error");
2523  origTarget = lfirst_node(ResTarget, orig_tl);
2524 
2525  attrno = attnameAttNum(pstate->p_target_relation,
2526  origTarget->name, true);
2527  if (attrno == InvalidAttrNumber)
2528  ereport(ERROR,
2529  (errcode(ERRCODE_UNDEFINED_COLUMN),
2530  errmsg("column \"%s\" of relation \"%s\" does not exist",
2531  origTarget->name,
2533  (origTarget->indirection != NIL &&
2534  strcmp(origTarget->name, pstate->p_target_nsitem->p_names->aliasname) == 0) ?
2535  errhint("SET target columns cannot be qualified with the relation name.") : 0,
2536  parser_errposition(pstate, origTarget->location)));
2537 
2538  updateTargetListEntry(pstate, tle, origTarget->name,
2539  attrno,
2540  origTarget->indirection,
2541  origTarget->location);
2542 
2543  /* Mark the target column as requiring update permissions */
2544  target_perminfo->updatedCols = bms_add_member(target_perminfo->updatedCols,
2546 
2547  orig_tl = lnext(origTlist, orig_tl);
2548  }
2549  if (orig_tl != NULL)
2550  elog(ERROR, "UPDATE target count mismatch --- internal error");
2551 
2552  return tlist;
2553 }
@ EXPR_KIND_UPDATE_SOURCE
Definition: parse_node.h:56
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
void updateTargetListEntry(ParseState *pstate, TargetEntry *tle, char *colname, int attrno, List *indirection, int location)
Definition: parse_target.c:619
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
#define RelationGetRelationName(relation)
Definition: rel.h:539
char * aliasname
Definition: primnodes.h:50
Bitmapset * updatedCols
Definition: parsenodes.h:1299

References Alias::aliasname, attnameAttNum(), bms_add_member(), elog, ereport, errcode(), errhint(), errmsg(), ERROR, EXPR_KIND_UPDATE_SOURCE, FirstLowInvalidHeapAttributeNumber, ResTarget::indirection, InvalidAttrNumber, lfirst, lfirst_node, list_head(), lnext(), ResTarget::location, ResTarget::name, NIL, ParseNamespaceItem::p_names, ParseState::p_next_resno, ParseNamespaceItem::p_perminfo, ParseState::p_target_nsitem, ParseState::p_target_relation, parser_errposition(), RelationGetNumberOfAttributes, RelationGetRelationName, TargetEntry::resno, transformTargetList(), RTEPermissionInfo::updatedCols, and updateTargetListEntry().

Referenced by transformMergeStmt(), transformOnConflictClause(), and transformUpdateStmt().

◆ transformValuesClause()

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

Definition at line 1480 of file analyze.c.

1481 {
1482  Query *qry = makeNode(Query);
1483  List *exprsLists = NIL;
1484  List *coltypes = NIL;
1485  List *coltypmods = NIL;
1486  List *colcollations = NIL;
1487  List **colexprs = NULL;
1488  int sublist_length = -1;
1489  bool lateral = false;
1490  ParseNamespaceItem *nsitem;
1491  ListCell *lc;
1492  ListCell *lc2;
1493  int i;
1494 
1495  qry->commandType = CMD_SELECT;
1496 
1497  /* Most SELECT stuff doesn't apply in a VALUES clause */
1498  Assert(stmt->distinctClause == NIL);
1499  Assert(stmt->intoClause == NULL);
1500  Assert(stmt->targetList == NIL);
1501  Assert(stmt->fromClause == NIL);
1502  Assert(stmt->whereClause == NULL);
1503  Assert(stmt->groupClause == NIL);
1504  Assert(stmt->havingClause == NULL);
1505  Assert(stmt->windowClause == NIL);
1506  Assert(stmt->op == SETOP_NONE);
1507 
1508  /* process the WITH clause independently of all else */
1509  if (stmt->withClause)
1510  {
1511  qry->hasRecursive = stmt->withClause->recursive;
1512  qry->cteList = transformWithClause(pstate, stmt->withClause);
1513  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1514  }
1515 
1516  /*
1517  * For each row of VALUES, transform the raw expressions.
1518  *
1519  * Note that the intermediate representation we build is column-organized
1520  * not row-organized. That simplifies the type and collation processing
1521  * below.
1522  */
1523  foreach(lc, stmt->valuesLists)
1524  {
1525  List *sublist = (List *) lfirst(lc);
1526 
1527  /*
1528  * Do basic expression transformation (same as a ROW() expr, but here
1529  * we disallow SetToDefault)
1530  */
1531  sublist = transformExpressionList(pstate, sublist,
1532  EXPR_KIND_VALUES, false);
1533 
1534  /*
1535  * All the sublists must be the same length, *after* transformation
1536  * (which might expand '*' into multiple items). The VALUES RTE can't
1537  * handle anything different.
1538  */
1539  if (sublist_length < 0)
1540  {
1541  /* Remember post-transformation length of first sublist */
1542  sublist_length = list_length(sublist);
1543  /* and allocate array for per-column lists */
1544  colexprs = (List **) palloc0(sublist_length * sizeof(List *));
1545  }
1546  else if (sublist_length != list_length(sublist))
1547  {
1548  ereport(ERROR,
1549  (errcode(ERRCODE_SYNTAX_ERROR),
1550  errmsg("VALUES lists must all be the same length"),
1551  parser_errposition(pstate,
1552  exprLocation((Node *) sublist))));
1553  }
1554 
1555  /* Build per-column expression lists */
1556  i = 0;
1557  foreach(lc2, sublist)
1558  {
1559  Node *col = (Node *) lfirst(lc2);
1560 
1561  colexprs[i] = lappend(colexprs[i], col);
1562  i++;
1563  }
1564 
1565  /* Release sub-list's cells to save memory */
1566  list_free(sublist);
1567 
1568  /* Prepare an exprsLists element for this row */
1569  exprsLists = lappend(exprsLists, NIL);
1570  }
1571 
1572  /*
1573  * Now resolve the common types of the columns, and coerce everything to
1574  * those types. Then identify the common typmod and common collation, if
1575  * any, of each column.
1576  *
1577  * We must do collation processing now because (1) assign_query_collations
1578  * doesn't process rangetable entries, and (2) we need to label the VALUES
1579  * RTE with column collations for use in the outer query. We don't
1580  * consider conflict of implicit collations to be an error here; instead
1581  * the column will just show InvalidOid as its collation, and you'll get a
1582  * failure later if that results in failure to resolve a collation.
1583  *
1584  * Note we modify the per-column expression lists in-place.
1585  */
1586  for (i = 0; i < sublist_length; i++)
1587  {
1588  Oid coltype;
1589  int32 coltypmod;
1590  Oid colcoll;
1591 
1592  coltype = select_common_type(pstate, colexprs[i], "VALUES", NULL);
1593 
1594  foreach(lc, colexprs[i])
1595  {
1596  Node *col = (Node *) lfirst(lc);
1597 
1598  col = coerce_to_common_type(pstate, col, coltype, "VALUES");
1599  lfirst(lc) = (void *) col;
1600  }
1601 
1602  coltypmod = select_common_typmod(pstate, colexprs[i], coltype);
1603  colcoll = select_common_collation(pstate, colexprs[i], true);
1604 
1605  coltypes = lappend_oid(coltypes, coltype);
1606  coltypmods = lappend_int(coltypmods, coltypmod);
1607  colcollations = lappend_oid(colcollations, colcoll);
1608  }
1609 
1610  /*
1611  * Finally, rearrange the coerced expressions into row-organized lists.
1612  */
1613  for (i = 0; i < sublist_length; i++)
1614  {
1615  forboth(lc, colexprs[i], lc2, exprsLists)
1616  {
1617  Node *col = (Node *) lfirst(lc);
1618  List *sublist = lfirst(lc2);
1619 
1620  sublist = lappend(sublist, col);
1621  lfirst(lc2) = sublist;
1622  }
1623  list_free(colexprs[i]);
1624  }
1625 
1626  /*
1627  * Ordinarily there can't be any current-level Vars in the expression
1628  * lists, because the namespace was empty ... but if we're inside CREATE
1629  * RULE, then NEW/OLD references might appear. In that case we have to
1630  * mark the VALUES RTE as LATERAL.
1631  */
1632  if (pstate->p_rtable != NIL &&
1633  contain_vars_of_level((Node *) exprsLists, 0))
1634  lateral = true;
1635 
1636  /*
1637  * Generate the VALUES RTE
1638  */
1639  nsitem = addRangeTableEntryForValues(pstate, exprsLists,
1640  coltypes, coltypmods, colcollations,
1641  NULL, lateral, true);
1642  addNSItemToQuery(pstate, nsitem, true, true, true);
1643 
1644  /*
1645  * Generate a targetlist as though expanding "*"
1646  */
1647  Assert(pstate->p_next_resno == 1);
1648  qry->targetList = expandNSItemAttrs(pstate, nsitem, 0, true, -1);
1649 
1650  /*
1651  * The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE to a
1652  * VALUES, so cope.
1653  */
1654  qry->sortClause = transformSortClause(pstate,
1655  stmt->sortClause,
1656  &qry->targetList,
1658  false /* allow SQL92 rules */ );
1659 
1660  qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
1661  EXPR_KIND_OFFSET, "OFFSET",
1662  stmt->limitOption);
1663  qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
1664  EXPR_KIND_LIMIT, "LIMIT",
1665  stmt->limitOption);
1666  qry->limitOption = stmt->limitOption;
1667 
1668  if (stmt->lockingClause)
1669  ereport(ERROR,
1670  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1671  /*------
1672  translator: %s is a SQL row locking clause such as FOR UPDATE */
1673  errmsg("%s cannot be applied to VALUES",
1675  linitial(stmt->lockingClause))->strength))));
1676 
1677  qry->rtable = pstate->p_rtable;
1678  qry->rteperminfos = pstate->p_rteperminfos;
1679  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
1680 
1681  qry->hasSubLinks = pstate->p_hasSubLinks;
1682 
1683  assign_query_collations(pstate, qry);
1684 
1685  return qry;
1686 }
void list_free(List *list)
Definition: list.c:1546
List * expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, bool require_col_privs, int location)

References addNSItemToQuery(), addRangeTableEntryForValues(), Assert, assign_query_collations(), CMD_SELECT, coerce_to_common_type(), Query::commandType, contain_vars_of_level(), Query::cteList, ereport, errcode(), errmsg(), ERROR, expandNSItemAttrs(), EXPR_KIND_LIMIT, EXPR_KIND_OFFSET, EXPR_KIND_ORDER_BY, EXPR_KIND_VALUES, exprLocation(), forboth, i, Query::jointree, lappend(), lappend_int(), lappend_oid(), LCS_asString(), lfirst, Query::limitCount, Query::limitOffset, Query::limitOption, linitial, list_free(), list_length(), makeFromExpr(), makeNode, NIL, ParseState::p_hasModifyingCTE, ParseState::p_hasSubLinks, ParseState::p_joinlist, ParseState::p_next_resno, ParseState::p_rtable, ParseState::p_rteperminfos, palloc0(), parser_errposition(), Query::rtable, select_common_collation(), select_common_type(), select_common_typmod(), SETOP_NONE, Query::sortClause, stmt, Query::targetList, transformExpressionList(), transformLimitClause(), transformSortClause(), and transformWithClause().

Referenced by transformStmt().

Variable Documentation

◆ post_parse_analyze_hook