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/guc.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 491 of file analyze.c.

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

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 3535 of file analyze.c.

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

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 1231 of file analyze.c.

1233 {
1234  List *result = NIL;
1235  int attno;
1236  Var *var;
1237  TargetEntry *te;
1238 
1239  /*
1240  * Note that resnos of the tlist must correspond to attnos of the
1241  * underlying relation, hence we need entries for dropped columns too.
1242  */
1243  for (attno = 0; attno < RelationGetNumberOfAttributes(targetrel); attno++)
1244  {
1245  Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno);
1246  char *name;
1247 
1248  if (attr->attisdropped)
1249  {
1250  /*
1251  * can't use atttypid here, but it doesn't really matter what type
1252  * the Const claims to be.
1253  */
1254  var = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
1255  name = NULL;
1256  }
1257  else
1258  {
1259  var = makeVar(exclRelIndex, attno + 1,
1260  attr->atttypid, attr->atttypmod,
1261  attr->attcollation,
1262  0);
1263  name = pstrdup(NameStr(attr->attname));
1264  }
1265 
1266  te = makeTargetEntry((Expr *) var,
1267  attno + 1,
1268  name,
1269  false);
1270 
1271  result = lappend(result, te);
1272  }
1273 
1274  /*
1275  * Add a whole-row-Var entry to support references to "EXCLUDED.*". Like
1276  * the other entries in the EXCLUDED tlist, its resno must match the Var's
1277  * varattno, else the wrong things happen while resolving references in
1278  * setrefs.c. This is against normal conventions for targetlists, but
1279  * it's okay since we don't use this as a real tlist.
1280  */
1281  var = makeVar(exclRelIndex, InvalidAttrNumber,
1282  targetrel->rd_rel->reltype,
1283  -1, InvalidOid, 0);
1284  te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
1285  result = lappend(result, te);
1286 
1287  return result;
1288 }
#define InvalidAttrNumber
Definition: attnum.h:23
#define NameStr(name)
Definition: c.h:749
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:1696
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 3244 of file analyze.c.

3245 {
3246  Assert(strength != LCS_NONE); /* else caller error */
3247 
3248  if (qry->setOperations)
3249  ereport(ERROR,
3250  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3251  /*------
3252  translator: %s is a SQL row locking clause such as FOR UPDATE */
3253  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
3254  LCS_asString(strength))));
3255  if (qry->distinctClause != NIL)
3256  ereport(ERROR,
3257  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3258  /*------
3259  translator: %s is a SQL row locking clause such as FOR UPDATE */
3260  errmsg("%s is not allowed with DISTINCT clause",
3261  LCS_asString(strength))));
3262  if (qry->groupClause != NIL || qry->groupingSets != NIL)
3263  ereport(ERROR,
3264  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3265  /*------
3266  translator: %s is a SQL row locking clause such as FOR UPDATE */
3267  errmsg("%s is not allowed with GROUP BY clause",
3268  LCS_asString(strength))));
3269  if (qry->havingQual != NULL)
3270  ereport(ERROR,
3271  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3272  /*------
3273  translator: %s is a SQL row locking clause such as FOR UPDATE */
3274  errmsg("%s is not allowed with HAVING clause",
3275  LCS_asString(strength))));
3276  if (qry->hasAggs)
3277  ereport(ERROR,
3278  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3279  /*------
3280  translator: %s is a SQL row locking clause such as FOR UPDATE */
3281  errmsg("%s is not allowed with aggregate functions",
3282  LCS_asString(strength))));
3283  if (qry->hasWindowFuncs)
3284  ereport(ERROR,
3285  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3286  /*------
3287  translator: %s is a SQL row locking clause such as FOR UPDATE */
3288  errmsg("%s is not allowed with window functions",
3289  LCS_asString(strength))));
3290  if (qry->hasTargetSRFs)
3291  ereport(ERROR,
3292  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3293  /*------
3294  translator: %s is a SQL row locking clause such as FOR UPDATE */
3295  errmsg("%s is not allowed with set-returning functions in the target list",
3296  LCS_asString(strength))));
3297 }
int errcode(int sqlerrcode)
Definition: elog.c:853
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:3219
Node * setOperations
Definition: parsenodes.h:221
List * groupClause
Definition: parsenodes.h:202
Node * havingQual
Definition: parsenodes.h:207
List * groupingSets
Definition: parsenodes.h:205
List * distinctClause
Definition: parsenodes.h:211

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 1301 of file analyze.c.

1302 {
1303  if (expr == NULL)
1304  return -1;
1305  if (IsA(expr, RowExpr))
1306  return list_length(((RowExpr *) expr)->args);
1307  if (IsA(expr, Var))
1308  {
1309  Var *var = (Var *) expr;
1310  AttrNumber attnum = var->varattno;
1311 
1312  if (attnum > 0 && var->vartype == RECORDOID)
1313  {
1314  RangeTblEntry *rte;
1315 
1316  rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup);
1317  if (rte->rtekind == RTE_SUBQUERY)
1318  {
1319  /* Subselect-in-FROM: examine sub-select's output expr */
1321  attnum);
1322 
1323  if (ste == NULL || ste->resjunk)
1324  return -1;
1325  expr = (Node *) ste->expr;
1326  if (IsA(expr, RowExpr))
1327  return list_length(((RowExpr *) expr)->args);
1328  }
1329  }
1330  }
1331  return -1;
1332 }
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:1018
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:193
Query * subquery
Definition: parsenodes.h:1104
RTEKind rtekind
Definition: parsenodes.h:1047
Expr * expr
Definition: primnodes.h:2186
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 2340 of file analyze.c.

2341 {
2342  Node *node;
2343  int leftmostRTI;
2344  Query *leftmostQuery;
2345  List *targetList;
2346  ListCell *left_tlist;
2347  ListCell *nrtl;
2348  int next_resno;
2349 
2350  /*
2351  * Find leftmost leaf SELECT
2352  */
2353  node = larg;
2354  while (node && IsA(node, SetOperationStmt))
2355  node = ((SetOperationStmt *) node)->larg;
2356  Assert(node && IsA(node, RangeTblRef));
2357  leftmostRTI = ((RangeTblRef *) node)->rtindex;
2358  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2359  Assert(leftmostQuery != NULL);
2360 
2361  /*
2362  * Generate dummy targetlist using column names of leftmost select and
2363  * dummy result expressions of the non-recursive term.
2364  */
2365  targetList = NIL;
2366  next_resno = 1;
2367 
2368  forboth(nrtl, nrtargetlist, left_tlist, leftmostQuery->targetList)
2369  {
2370  TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
2371  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
2372  char *colName;
2373  TargetEntry *tle;
2374 
2375  Assert(!lefttle->resjunk);
2376  colName = pstrdup(lefttle->resname);
2377  tle = makeTargetEntry(nrtle->expr,
2378  next_resno++,
2379  colName,
2380  false);
2381  targetList = lappend(targetList, tle);
2382  }
2383 
2384  /* Now build CTE's output column info using dummy targetlist */
2385  analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
2386 }
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:208
List * p_rtable
Definition: parse_node.h:196

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 3219 of file analyze.c.

3220 {
3221  switch (strength)
3222  {
3223  case LCS_NONE:
3224  Assert(false);
3225  break;
3226  case LCS_FORKEYSHARE:
3227  return "FOR KEY SHARE";
3228  case LCS_FORSHARE:
3229  return "FOR SHARE";
3230  case LCS_FORNOKEYUPDATE:
3231  return "FOR NO KEY UPDATE";
3232  case LCS_FORUPDATE:
3233  return "FOR UPDATE";
3234  }
3235  return "FOR some"; /* shouldn't happen */
3236 }
@ 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 1962 of file analyze.c.

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

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 105 of file analyze.c.

108 {
109  ParseState *pstate = make_parsestate(NULL);
110  Query *query;
111  JumbleState *jstate = NULL;
112 
113  Assert(sourceText != NULL); /* required as of 8.4 */
114 
115  pstate->p_sourcetext = sourceText;
116 
117  if (numParams > 0)
118  setup_parse_fixed_parameters(pstate, paramTypes, numParams);
119 
120  pstate->p_queryEnv = queryEnv;
121 
122  query = transformTopLevelStmt(pstate, parseTree);
123 
124  if (IsQueryIdEnabled())
125  jstate = JumbleQuery(query);
126 
128  (*post_parse_analyze_hook) (pstate, query, jstate);
129 
130  free_parsestate(pstate);
131 
132  pgstat_report_query_id(query->queryId, false);
133 
134  return query;
135 }
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:68
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:249
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:59
static bool IsQueryIdEnabled(void)
Definition: queryjumble.h:77
JumbleState * JumbleQuery(Query *query)
QueryEnvironment * p_queryEnv
Definition: parse_node.h:223
const char * p_sourcetext
Definition: parse_node.h:195

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 145 of file analyze.c.

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

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 186 of file analyze.c.

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

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 222 of file analyze.c.

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

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 447 of file analyze.c.

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

References nodeTag, and RawStmt::stmt.

Referenced by analyze_requires_snapshot().

◆ transformCallStmt()

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

Definition at line 3094 of file analyze.c.

3095 {
3096  List *targs;
3097  ListCell *lc;
3098  Node *node;
3099  FuncExpr *fexpr;
3100  HeapTuple proctup;
3101  Datum proargmodes;
3102  bool isNull;
3103  List *outargs = NIL;
3104  Query *result;
3105 
3106  /*
3107  * First, do standard parse analysis on the procedure call and its
3108  * arguments, allowing us to identify the called procedure.
3109  */
3110  targs = NIL;
3111  foreach(lc, stmt->funccall->args)
3112  {
3113  targs = lappend(targs, transformExpr(pstate,
3114  (Node *) lfirst(lc),
3116  }
3117 
3118  node = ParseFuncOrColumn(pstate,
3119  stmt->funccall->funcname,
3120  targs,
3121  pstate->p_last_srf,
3122  stmt->funccall,
3123  true,
3124  stmt->funccall->location);
3125 
3126  assign_expr_collations(pstate, node);
3127 
3128  fexpr = castNode(FuncExpr, node);
3129 
3130  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
3131  if (!HeapTupleIsValid(proctup))
3132  elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
3133 
3134  /*
3135  * Expand the argument list to deal with named-argument notation and
3136  * default arguments. For ordinary FuncExprs this'd be done during
3137  * planning, but a CallStmt doesn't go through planning, and there seems
3138  * no good reason not to do it here.
3139  */
3140  fexpr->args = expand_function_arguments(fexpr->args,
3141  true,
3142  fexpr->funcresulttype,
3143  proctup);
3144 
3145  /* Fetch proargmodes; if it's null, there are no output args */
3146  proargmodes = SysCacheGetAttr(PROCOID, proctup,
3147  Anum_pg_proc_proargmodes,
3148  &isNull);
3149  if (!isNull)
3150  {
3151  /*
3152  * Split the list into input arguments in fexpr->args and output
3153  * arguments in stmt->outargs. INOUT arguments appear in both lists.
3154  */
3155  ArrayType *arr;
3156  int numargs;
3157  char *argmodes;
3158  List *inargs;
3159  int i;
3160 
3161  arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
3162  numargs = list_length(fexpr->args);
3163  if (ARR_NDIM(arr) != 1 ||
3164  ARR_DIMS(arr)[0] != numargs ||
3165  ARR_HASNULL(arr) ||
3166  ARR_ELEMTYPE(arr) != CHAROID)
3167  elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
3168  numargs);
3169  argmodes = (char *) ARR_DATA_PTR(arr);
3170 
3171  inargs = NIL;
3172  i = 0;
3173  foreach(lc, fexpr->args)
3174  {
3175  Node *n = lfirst(lc);
3176 
3177  switch (argmodes[i])
3178  {
3179  case PROARGMODE_IN:
3180  case PROARGMODE_VARIADIC:
3181  inargs = lappend(inargs, n);
3182  break;
3183  case PROARGMODE_OUT:
3184  outargs = lappend(outargs, n);
3185  break;
3186  case PROARGMODE_INOUT:
3187  inargs = lappend(inargs, n);
3188  outargs = lappend(outargs, copyObject(n));
3189  break;
3190  default:
3191  /* note we don't support PROARGMODE_TABLE */
3192  elog(ERROR, "invalid argmode %c for procedure",
3193  argmodes[i]);
3194  break;
3195  }
3196  i++;
3197  }
3198  fexpr->args = inargs;
3199  }
3200 
3201  stmt->funcexpr = fexpr;
3202  stmt->outargs = outargs;
3203 
3204  ReleaseSysCache(proctup);
3205 
3206  /* represent the command as a utility Query */
3207  result = makeNode(Query);
3208  result->commandType = CMD_UTILITY;
3209  result->utilityStmt = (Node *) stmt;
3210 
3211  return result;
3212 }
#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:225
#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:120
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:232
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:136
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:596

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 3019 of file analyze.c.

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

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 2874 of file analyze.c.

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

515 {
516  Query *qry = makeNode(Query);
517  ParseNamespaceItem *nsitem;
518  Node *qual;
519 
520  qry->commandType = CMD_DELETE;
521 
522  /* process the WITH clause independently of all else */
523  if (stmt->withClause)
524  {
525  qry->hasRecursive = stmt->withClause->recursive;
526  qry->cteList = transformWithClause(pstate, stmt->withClause);
527  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
528  }
529 
530  /* set up range table with just the result rel */
531  qry->resultRelation = setTargetTable(pstate, stmt->relation,
532  stmt->relation->inh,
533  true,
534  ACL_DELETE);
535  nsitem = pstate->p_target_nsitem;
536 
537  /* there's no DISTINCT in DELETE */
538  qry->distinctClause = NIL;
539 
540  /* subqueries in USING cannot access the result relation */
541  nsitem->p_lateral_only = true;
542  nsitem->p_lateral_ok = false;
543 
544  /*
545  * The USING clause is non-standard SQL syntax, and is equivalent in
546  * functionality to the FROM list that can be specified for UPDATE. The
547  * USING keyword is used rather than FROM because FROM is already a
548  * keyword in the DELETE syntax.
549  */
550  transformFromClause(pstate, stmt->usingClause);
551 
552  /* remaining clauses can reference the result relation normally */
553  nsitem->p_lateral_only = false;
554  nsitem->p_lateral_ok = true;
555 
556  qual = transformWhereClause(pstate, stmt->whereClause,
557  EXPR_KIND_WHERE, "WHERE");
558 
559  qry->returningList = transformReturningList(pstate, stmt->returningList,
561 
562  /* done building the range table and jointree */
563  qry->rtable = pstate->p_rtable;
564  qry->rteperminfos = pstate->p_rteperminfos;
565  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
566 
567  qry->hasSubLinks = pstate->p_hasSubLinks;
568  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
569  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
570  qry->hasAggs = pstate->p_hasAggs;
571 
572  assign_query_collations(pstate, qry);
573 
574  /* this must be done after collations, for reliable comparison of exprs */
575  if (pstate->p_hasAggs)
576  parseCheckAggregates(pstate, qry);
577 
578  return qry;
579 }
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:1085
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:2566
bool p_hasTargetSRFs
Definition: parse_node.h:228
bool p_hasWindowFuncs
Definition: parse_node.h:227
ParseNamespaceItem * p_target_nsitem
Definition: parse_node.h:210
bool p_hasModifyingCTE
Definition: parse_node.h:230
List * p_rteperminfos
Definition: parse_node.h:197
bool p_hasSubLinks
Definition: parse_node.h:229
List * p_joinlist
Definition: parse_node.h:201
bool p_hasAggs
Definition: parse_node.h:226
FromExpr * jointree
Definition: parsenodes.h:177
List * returningList
Definition: parsenodes.h:200
List * cteList
Definition: parsenodes.h:168
List * rtable
Definition: parsenodes.h:170

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 2967 of file analyze.c.

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

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 1014 of file analyze.c.

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

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

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 3308 of file analyze.c.

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

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

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 273 of file analyze.c.

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

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 2625 of file analyze.c.

2626 {
2627  Query *qry = makeNode(Query);
2628  ColumnRef *cref = makeNode(ColumnRef);
2629  List *indirection = stmt->indirection;
2630  int nnames = stmt->nnames;
2631  SelectStmt *sstmt = stmt->val;
2632  Node *target;
2633  Oid targettype;
2634  int32 targettypmod;
2635  Oid targetcollation;
2636  List *tlist;
2637  TargetEntry *tle;
2638  Oid type_id;
2639  Node *qual;
2640  ListCell *l;
2641 
2642  /*
2643  * First, construct a ColumnRef for the target variable. If the target
2644  * has more than one dotted name, we have to pull the extra names out of
2645  * the indirection list.
2646  */
2647  cref->fields = list_make1(makeString(stmt->name));
2648  cref->location = stmt->location;
2649  if (nnames > 1)
2650  {
2651  /* avoid munging the raw parsetree */
2652  indirection = list_copy(indirection);
2653  while (--nnames > 0 && indirection != NIL)
2654  {
2655  Node *ind = (Node *) linitial(indirection);
2656 
2657  if (!IsA(ind, String))
2658  elog(ERROR, "invalid name count in PLAssignStmt");
2659  cref->fields = lappend(cref->fields, ind);
2660  indirection = list_delete_first(indirection);
2661  }
2662  }
2663 
2664  /*
2665  * Transform the target reference. Typically we will get back a Param
2666  * node, but there's no reason to be too picky about its type.
2667  */
2668  target = transformExpr(pstate, (Node *) cref,
2670  targettype = exprType(target);
2671  targettypmod = exprTypmod(target);
2672  targetcollation = exprCollation(target);
2673 
2674  /*
2675  * The rest mostly matches transformSelectStmt, except that we needn't
2676  * consider WITH or INTO, and we build a targetlist our own way.
2677  */
2678  qry->commandType = CMD_SELECT;
2679  pstate->p_is_insert = false;
2680 
2681  /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
2682  pstate->p_locking_clause = sstmt->lockingClause;
2683 
2684  /* make WINDOW info available for window functions, too */
2685  pstate->p_windowdefs = sstmt->windowClause;
2686 
2687  /* process the FROM clause */
2688  transformFromClause(pstate, sstmt->fromClause);
2689 
2690  /* initially transform the targetlist as if in SELECT */
2691  tlist = transformTargetList(pstate, sstmt->targetList,
2693 
2694  /* we should have exactly one targetlist item */
2695  if (list_length(tlist) != 1)
2696  ereport(ERROR,
2697  (errcode(ERRCODE_SYNTAX_ERROR),
2698  errmsg_plural("assignment source returned %d column",
2699  "assignment source returned %d columns",
2700  list_length(tlist),
2701  list_length(tlist))));
2702 
2703  tle = linitial_node(TargetEntry, tlist);
2704 
2705  /*
2706  * This next bit is similar to transformAssignedExpr; the key difference
2707  * is we use COERCION_PLPGSQL not COERCION_ASSIGNMENT.
2708  */
2709  type_id = exprType((Node *) tle->expr);
2710 
2712 
2713  if (indirection)
2714  {
2715  tle->expr = (Expr *)
2717  target,
2718  stmt->name,
2719  false,
2720  targettype,
2721  targettypmod,
2722  targetcollation,
2723  indirection,
2724  list_head(indirection),
2725  (Node *) tle->expr,
2727  exprLocation(target));
2728  }
2729  else if (targettype != type_id &&
2730  (targettype == RECORDOID || ISCOMPLEX(targettype)) &&
2731  (type_id == RECORDOID || ISCOMPLEX(type_id)))
2732  {
2733  /*
2734  * Hack: do not let coerce_to_target_type() deal with inconsistent
2735  * composite types. Just pass the expression result through as-is,
2736  * and let the PL/pgSQL executor do the conversion its way. This is
2737  * rather bogus, but it's needed for backwards compatibility.
2738  */
2739  }
2740  else
2741  {
2742  /*
2743  * For normal non-qualified target column, do type checking and
2744  * coercion.
2745  */
2746  Node *orig_expr = (Node *) tle->expr;
2747 
2748  tle->expr = (Expr *)
2749  coerce_to_target_type(pstate,
2750  orig_expr, type_id,
2751  targettype, targettypmod,
2754  -1);
2755  /* With COERCION_PLPGSQL, this error is probably unreachable */
2756  if (tle->expr == NULL)
2757  ereport(ERROR,
2758  (errcode(ERRCODE_DATATYPE_MISMATCH),
2759  errmsg("variable \"%s\" is of type %s"
2760  " but expression is of type %s",
2761  stmt->name,
2762  format_type_be(targettype),
2763  format_type_be(type_id)),
2764  errhint("You will need to rewrite or cast the expression."),
2765  parser_errposition(pstate, exprLocation(orig_expr))));
2766  }
2767 
2768  pstate->p_expr_kind = EXPR_KIND_NONE;
2769 
2770  qry->targetList = list_make1(tle);
2771 
2772  /* transform WHERE */
2773  qual = transformWhereClause(pstate, sstmt->whereClause,
2774  EXPR_KIND_WHERE, "WHERE");
2775 
2776  /* initial processing of HAVING clause is much like WHERE clause */
2777  qry->havingQual = transformWhereClause(pstate, sstmt->havingClause,
2778  EXPR_KIND_HAVING, "HAVING");
2779 
2780  /*
2781  * Transform sorting/grouping stuff. Do ORDER BY first because both
2782  * transformGroupClause and transformDistinctClause need the results. Note
2783  * that these functions can also change the targetList, so it's passed to
2784  * them by reference.
2785  */
2786  qry->sortClause = transformSortClause(pstate,
2787  sstmt->sortClause,
2788  &qry->targetList,
2790  false /* allow SQL92 rules */ );
2791 
2792  qry->groupClause = transformGroupClause(pstate,
2793  sstmt->groupClause,
2794  &qry->groupingSets,
2795  &qry->targetList,
2796  qry->sortClause,
2798  false /* allow SQL92 rules */ );
2799 
2800  if (sstmt->distinctClause == NIL)
2801  {
2802  qry->distinctClause = NIL;
2803  qry->hasDistinctOn = false;
2804  }
2805  else if (linitial(sstmt->distinctClause) == NULL)
2806  {
2807  /* We had SELECT DISTINCT */
2809  &qry->targetList,
2810  qry->sortClause,
2811  false);
2812  qry->hasDistinctOn = false;
2813  }
2814  else
2815  {
2816  /* We had SELECT DISTINCT ON */
2818  sstmt->distinctClause,
2819  &qry->targetList,
2820  qry->sortClause);
2821  qry->hasDistinctOn = true;
2822  }
2823 
2824  /* transform LIMIT */
2825  qry->limitOffset = transformLimitClause(pstate, sstmt->limitOffset,
2826  EXPR_KIND_OFFSET, "OFFSET",
2827  sstmt->limitOption);
2828  qry->limitCount = transformLimitClause(pstate, sstmt->limitCount,
2829  EXPR_KIND_LIMIT, "LIMIT",
2830  sstmt->limitOption);
2831  qry->limitOption = sstmt->limitOption;
2832 
2833  /* transform window clauses after we have seen all window functions */
2835  pstate->p_windowdefs,
2836  &qry->targetList);
2837 
2838  qry->rtable = pstate->p_rtable;
2839  qry->rteperminfos = pstate->p_rteperminfos;
2840  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2841 
2842  qry->hasSubLinks = pstate->p_hasSubLinks;
2843  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
2844  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2845  qry->hasAggs = pstate->p_hasAggs;
2846 
2847  foreach(l, sstmt->lockingClause)
2848  {
2849  transformLockingClause(pstate, qry,
2850  (LockingClause *) lfirst(l), false);
2851  }
2852 
2853  assign_query_collations(pstate, qry);
2854 
2855  /* this must be done after collations, for reliable comparison of exprs */
2856  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
2857  parseCheckAggregates(pstate, qry);
2858 
2859  return qry;
2860 }
signed int int32
Definition: c.h:497
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:686
#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:297
List * fields
Definition: parsenodes.h:296
ParseExprKind p_expr_kind
Definition: parse_node.h:214
List * p_windowdefs
Definition: parse_node.h:213
List * p_locking_clause
Definition: parse_node.h:217
Node * limitCount
Definition: parsenodes.h:216
Node * limitOffset
Definition: parsenodes.h:215
LimitOption limitOption
Definition: parsenodes.h:217
List * windowClause
Definition: parsenodes.h:209
List * sortClause
Definition: parsenodes.h:213
LimitOption limitOption
Definition: parsenodes.h:2150
List * targetList
Definition: parsenodes.h:2125
List * fromClause
Definition: parsenodes.h:2126
List * groupClause
Definition: parsenodes.h:2128
Node * havingClause
Definition: parsenodes.h:2130
List * windowClause
Definition: parsenodes.h:2131
List * distinctClause
Definition: parsenodes.h:2122
Node * whereClause
Definition: parsenodes.h:2127
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 2566 of file analyze.c.

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

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 2394 of file analyze.c.

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

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 1343 of file analyze.c.

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

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 1705 of file analyze.c.

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

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 2009 of file analyze.c.

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

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 312 of file analyze.c.

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

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 249 of file analyze.c.

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

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 2425 of file analyze.c.

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

2492 {
2493  List *tlist = NIL;
2494  RTEPermissionInfo *target_perminfo;
2495  ListCell *orig_tl;
2496  ListCell *tl;
2497 
2498  tlist = transformTargetList(pstate, origTlist,
2500 
2501  /* Prepare to assign non-conflicting resnos to resjunk attributes */
2504 
2505  /* Prepare non-junk columns for assignment to target table */
2506  target_perminfo = pstate->p_target_nsitem->p_perminfo;
2507  orig_tl = list_head(origTlist);
2508 
2509  foreach(tl, tlist)
2510  {
2511  TargetEntry *tle = (TargetEntry *) lfirst(tl);
2512  ResTarget *origTarget;
2513  int attrno;
2514 
2515  if (tle->resjunk)
2516  {
2517  /*
2518  * Resjunk nodes need no additional processing, but be sure they
2519  * have resnos that do not match any target columns; else rewriter
2520  * or planner might get confused. They don't need a resname
2521  * either.
2522  */
2523  tle->resno = (AttrNumber) pstate->p_next_resno++;
2524  tle->resname = NULL;
2525  continue;
2526  }
2527  if (orig_tl == NULL)
2528  elog(ERROR, "UPDATE target count mismatch --- internal error");
2529  origTarget = lfirst_node(ResTarget, orig_tl);
2530 
2531  attrno = attnameAttNum(pstate->p_target_relation,
2532  origTarget->name, true);
2533  if (attrno == InvalidAttrNumber)
2534  ereport(ERROR,
2535  (errcode(ERRCODE_UNDEFINED_COLUMN),
2536  errmsg("column \"%s\" of relation \"%s\" does not exist",
2537  origTarget->name,
2539  (origTarget->indirection != NIL &&
2540  strcmp(origTarget->name, pstate->p_target_nsitem->p_names->aliasname) == 0) ?
2541  errhint("SET target columns cannot be qualified with the relation name.") : 0,
2542  parser_errposition(pstate, origTarget->location)));
2543 
2544  updateTargetListEntry(pstate, tle, origTarget->name,
2545  attrno,
2546  origTarget->indirection,
2547  origTarget->location);
2548 
2549  /* Mark the target column as requiring update permissions */
2550  target_perminfo->updatedCols = bms_add_member(target_perminfo->updatedCols,
2552 
2553  orig_tl = lnext(origTlist, orig_tl);
2554  }
2555  if (orig_tl != NULL)
2556  elog(ERROR, "UPDATE target count mismatch --- internal error");
2557 
2558  return tlist;
2559 }
@ 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:622
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:1295

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 1486 of file analyze.c.

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