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 "rewrite/rewriteManip.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 ListtransformReturningList (ParseState *pstate, List *returningList)
 
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)
 
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 488 of file analyze.c.

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

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

3516 {
3517  RowMarkClause *rc;
3518 
3519  Assert(strength != LCS_NONE); /* else caller error */
3520 
3521  /* If it's an explicit clause, make sure hasForUpdate gets set */
3522  if (!pushedDown)
3523  qry->hasForUpdate = true;
3524 
3525  /* Check for pre-existing entry for same rtindex */
3526  if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
3527  {
3528  /*
3529  * If the same RTE is specified with more than one locking strength,
3530  * use the strongest. (Reasonable, since you can't take both a shared
3531  * and exclusive lock at the same time; it'll end up being exclusive
3532  * anyway.)
3533  *
3534  * Similarly, if the same RTE is specified with more than one lock
3535  * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
3536  * turn wins over waiting for the lock (the default). This is a bit
3537  * more debatable but raising an error doesn't seem helpful. (Consider
3538  * for instance SELECT FOR UPDATE NOWAIT from a view that internally
3539  * contains a plain FOR UPDATE spec.) Having NOWAIT win over SKIP
3540  * LOCKED is reasonable since the former throws an error in case of
3541  * coming across a locked tuple, which may be undesirable in some
3542  * cases but it seems better than silently returning inconsistent
3543  * results.
3544  *
3545  * And of course pushedDown becomes false if any clause is explicit.
3546  */
3547  rc->strength = Max(rc->strength, strength);
3548  rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
3549  rc->pushedDown &= pushedDown;
3550  return;
3551  }
3552 
3553  /* Make a new RowMarkClause */
3554  rc = makeNode(RowMarkClause);
3555  rc->rti = rtindex;
3556  rc->strength = strength;
3557  rc->waitPolicy = waitPolicy;
3558  rc->pushedDown = pushedDown;
3559  qry->rowMarks = lappend(qry->rowMarks, rc);
3560 }
#define Max(x, y)
Definition: c.h:987
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:338
@ LCS_NONE
Definition: lockoptions.h:23
#define makeNode(_type_)
Definition: nodes.h:176
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
List * rowMarks
Definition: parsenodes.h:214
LockClauseStrength strength
Definition: parsenodes.h:1535
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1536

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

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

3223 {
3224  Assert(strength != LCS_NONE); /* else caller error */
3225 
3226  if (qry->setOperations)
3227  ereport(ERROR,
3228  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3229  /*------
3230  translator: %s is a SQL row locking clause such as FOR UPDATE */
3231  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
3232  LCS_asString(strength))));
3233  if (qry->distinctClause != NIL)
3234  ereport(ERROR,
3235  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3236  /*------
3237  translator: %s is a SQL row locking clause such as FOR UPDATE */
3238  errmsg("%s is not allowed with DISTINCT clause",
3239  LCS_asString(strength))));
3240  if (qry->groupClause != NIL || qry->groupingSets != NIL)
3241  ereport(ERROR,
3242  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3243  /*------
3244  translator: %s is a SQL row locking clause such as FOR UPDATE */
3245  errmsg("%s is not allowed with GROUP BY clause",
3246  LCS_asString(strength))));
3247  if (qry->havingQual != NULL)
3248  ereport(ERROR,
3249  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3250  /*------
3251  translator: %s is a SQL row locking clause such as FOR UPDATE */
3252  errmsg("%s is not allowed with HAVING clause",
3253  LCS_asString(strength))));
3254  if (qry->hasAggs)
3255  ereport(ERROR,
3256  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3257  /*------
3258  translator: %s is a SQL row locking clause such as FOR UPDATE */
3259  errmsg("%s is not allowed with aggregate functions",
3260  LCS_asString(strength))));
3261  if (qry->hasWindowFuncs)
3262  ereport(ERROR,
3263  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3264  /*------
3265  translator: %s is a SQL row locking clause such as FOR UPDATE */
3266  errmsg("%s is not allowed with window functions",
3267  LCS_asString(strength))));
3268  if (qry->hasTargetSRFs)
3269  ereport(ERROR,
3270  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3271  /*------
3272  translator: %s is a SQL row locking clause such as FOR UPDATE */
3273  errmsg("%s is not allowed with set-returning functions in the target list",
3274  LCS_asString(strength))));
3275 }
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:3197
Node * setOperations
Definition: parsenodes.h:216
List * groupClause
Definition: parsenodes.h:197
Node * havingQual
Definition: parsenodes.h:202
List * groupingSets
Definition: parsenodes.h:200
List * distinctClause
Definition: parsenodes.h:206

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

1286 {
1287  if (expr == NULL)
1288  return -1;
1289  if (IsA(expr, RowExpr))
1290  return list_length(((RowExpr *) expr)->args);
1291  if (IsA(expr, Var))
1292  {
1293  Var *var = (Var *) expr;
1294  AttrNumber attnum = var->varattno;
1295 
1296  if (attnum > 0 && var->vartype == RECORDOID)
1297  {
1298  RangeTblEntry *rte;
1299 
1300  rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup);
1301  if (rte->rtekind == RTE_SUBQUERY)
1302  {
1303  /* Subselect-in-FROM: examine sub-select's output expr */
1305  attnum);
1306 
1307  if (ste == NULL || ste->resjunk)
1308  return -1;
1309  expr = (Node *) ste->expr;
1310  if (IsA(expr, RowExpr))
1311  return list_length(((RowExpr *) expr)->args);
1312  }
1313  }
1314  }
1315  return -1;
1316 }
int16 AttrNumber
Definition: attnum.h:21
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
@ RTE_SUBQUERY
Definition: parsenodes.h:1014
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:188
Query * subquery
Definition: parsenodes.h:1080
RTEKind rtekind
Definition: parsenodes.h:1032
Expr * expr
Definition: primnodes.h:1895
AttrNumber varattno
Definition: primnodes.h:238
int varno
Definition: primnodes.h:233
Index varlevelsup
Definition: primnodes.h:258

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

2324 {
2325  Node *node;
2326  int leftmostRTI;
2327  Query *leftmostQuery;
2328  List *targetList;
2329  ListCell *left_tlist;
2330  ListCell *nrtl;
2331  int next_resno;
2332 
2333  /*
2334  * Find leftmost leaf SELECT
2335  */
2336  node = larg;
2337  while (node && IsA(node, SetOperationStmt))
2338  node = ((SetOperationStmt *) node)->larg;
2339  Assert(node && IsA(node, RangeTblRef));
2340  leftmostRTI = ((RangeTblRef *) node)->rtindex;
2341  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2342  Assert(leftmostQuery != NULL);
2343 
2344  /*
2345  * Generate dummy targetlist using column names of leftmost select and
2346  * dummy result expressions of the non-recursive term.
2347  */
2348  targetList = NIL;
2349  next_resno = 1;
2350 
2351  forboth(nrtl, nrtargetlist, left_tlist, leftmostQuery->targetList)
2352  {
2353  TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
2354  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
2355  char *colName;
2356  TargetEntry *tle;
2357 
2358  Assert(!lefttle->resjunk);
2359  colName = pstrdup(lefttle->resname);
2360  tle = makeTargetEntry(nrtle->expr,
2361  next_resno++,
2362  colName,
2363  false);
2364  targetList = lappend(targetList, tle);
2365  }
2366 
2367  /* Now build CTE's output column info using dummy targetlist */
2368  analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
2369 }
void analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
Definition: parse_cte.c:576
#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:467
CommonTableExpr * p_parent_cte
Definition: parse_node.h:205
List * p_rtable
Definition: parse_node.h:193

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

3198 {
3199  switch (strength)
3200  {
3201  case LCS_NONE:
3202  Assert(false);
3203  break;
3204  case LCS_FORKEYSHARE:
3205  return "FOR KEY SHARE";
3206  case LCS_FORSHARE:
3207  return "FOR SHARE";
3208  case LCS_FORNOKEYUPDATE:
3209  return "FOR NO KEY UPDATE";
3210  case LCS_FORUPDATE:
3211  return "FOR UPDATE";
3212  }
3213  return "FOR some"; /* shouldn't happen */
3214 }
@ 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 1945 of file analyze.c.

1946 {
1948  Oid sortop;
1949  Oid eqop;
1950  bool hashable;
1951 
1952  /* determine the eqop and optional sortop */
1953  get_sort_group_operators(rescoltype,
1954  false, true, false,
1955  &sortop, &eqop, NULL,
1956  &hashable);
1957 
1958  /*
1959  * The type cache doesn't believe that record is hashable (see
1960  * cache_record_field_properties()), but if the caller really needs hash
1961  * support, we can assume it does. Worst case, if any components of the
1962  * record don't support hashing, we will fail at execution.
1963  */
1964  if (require_hash && (rescoltype == RECORDOID || rescoltype == RECORDARRAYOID))
1965  hashable = true;
1966 
1967  /* we don't have a tlist yet, so can't assign sortgrouprefs */
1968  grpcl->tleSortGroupRef = 0;
1969  grpcl->eqop = eqop;
1970  grpcl->sortop = sortop;
1971  grpcl->nulls_first = false; /* OK with or without sortop */
1972  grpcl->hashable = hashable;
1973 
1974  return grpcl;
1975 }
void get_sort_group_operators(Oid argtype, bool needLT, bool needEQ, bool needGT, Oid *ltOpr, Oid *eqOpr, Oid *gtOpr, bool *isHashable)
Definition: parse_oper.c:192
unsigned int Oid
Definition: postgres_ext.h:31
Index tleSortGroupRef
Definition: parsenodes.h:1392

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

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

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

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

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

Referenced by pg_analyze_and_rewrite_varparams().

◆ parse_analyze_withcb()

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

Definition at line 188 of file analyze.c.

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

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

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

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

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

References nodeTag, and RawStmt::stmt.

Referenced by analyze_requires_snapshot().

◆ transformCallStmt()

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

Definition at line 3072 of file analyze.c.

3073 {
3074  List *targs;
3075  ListCell *lc;
3076  Node *node;
3077  FuncExpr *fexpr;
3078  HeapTuple proctup;
3079  Datum proargmodes;
3080  bool isNull;
3081  List *outargs = NIL;
3082  Query *result;
3083 
3084  /*
3085  * First, do standard parse analysis on the procedure call and its
3086  * arguments, allowing us to identify the called procedure.
3087  */
3088  targs = NIL;
3089  foreach(lc, stmt->funccall->args)
3090  {
3091  targs = lappend(targs, transformExpr(pstate,
3092  (Node *) lfirst(lc),
3094  }
3095 
3096  node = ParseFuncOrColumn(pstate,
3097  stmt->funccall->funcname,
3098  targs,
3099  pstate->p_last_srf,
3100  stmt->funccall,
3101  true,
3102  stmt->funccall->location);
3103 
3104  assign_expr_collations(pstate, node);
3105 
3106  fexpr = castNode(FuncExpr, node);
3107 
3108  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
3109  if (!HeapTupleIsValid(proctup))
3110  elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
3111 
3112  /*
3113  * Expand the argument list to deal with named-argument notation and
3114  * default arguments. For ordinary FuncExprs this'd be done during
3115  * planning, but a CallStmt doesn't go through planning, and there seems
3116  * no good reason not to do it here.
3117  */
3118  fexpr->args = expand_function_arguments(fexpr->args,
3119  true,
3120  fexpr->funcresulttype,
3121  proctup);
3122 
3123  /* Fetch proargmodes; if it's null, there are no output args */
3124  proargmodes = SysCacheGetAttr(PROCOID, proctup,
3125  Anum_pg_proc_proargmodes,
3126  &isNull);
3127  if (!isNull)
3128  {
3129  /*
3130  * Split the list into input arguments in fexpr->args and output
3131  * arguments in stmt->outargs. INOUT arguments appear in both lists.
3132  */
3133  ArrayType *arr;
3134  int numargs;
3135  char *argmodes;
3136  List *inargs;
3137  int i;
3138 
3139  arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
3140  numargs = list_length(fexpr->args);
3141  if (ARR_NDIM(arr) != 1 ||
3142  ARR_DIMS(arr)[0] != numargs ||
3143  ARR_HASNULL(arr) ||
3144  ARR_ELEMTYPE(arr) != CHAROID)
3145  elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
3146  numargs);
3147  argmodes = (char *) ARR_DATA_PTR(arr);
3148 
3149  inargs = NIL;
3150  i = 0;
3151  foreach(lc, fexpr->args)
3152  {
3153  Node *n = lfirst(lc);
3154 
3155  switch (argmodes[i])
3156  {
3157  case PROARGMODE_IN:
3158  case PROARGMODE_VARIADIC:
3159  inargs = lappend(inargs, n);
3160  break;
3161  case PROARGMODE_OUT:
3162  outargs = lappend(outargs, n);
3163  break;
3164  case PROARGMODE_INOUT:
3165  inargs = lappend(inargs, n);
3166  outargs = lappend(outargs, copyObject(n));
3167  break;
3168  default:
3169  /* note we don't support PROARGMODE_TABLE */
3170  elog(ERROR, "invalid argmode %c for procedure",
3171  argmodes[i]);
3172  break;
3173  }
3174  i++;
3175  }
3176  fexpr->args = inargs;
3177  }
3178 
3179  stmt->funcexpr = fexpr;
3180  stmt->outargs = outargs;
3181 
3182  ReleaseSysCache(proctup);
3183 
3184  /* represent the command as a utility Query */
3185  result = makeNode(Query);
3186  result->commandType = CMD_UTILITY;
3187  result->utilityStmt = (Node *) stmt;
3188 
3189  return result;
3190 }
#define ARR_NDIM(a)
Definition: array.h:283
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define DatumGetArrayTypeP(X)
Definition: array.h:254
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_HASNULL(a)
Definition: array.h:284
List * expand_function_arguments(List *args, bool include_out_arguments, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:4068
#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:244
@ CMD_UTILITY
Definition: nodes.h:281
#define castNode(_type_, nodeptr)
Definition: nodes.h:197
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:110
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:80
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
Oid funcid
Definition: primnodes.h:677
List * args
Definition: primnodes.h:695
Node * p_last_srf
Definition: parse_node.h:228
CmdType commandType
Definition: parsenodes.h:127
Node * utilityStmt
Definition: parsenodes.h:142
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1081
@ PROCOID
Definition: syscache.h:79

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(), PROCOID, ReleaseSysCache(), SearchSysCache1(), stmt, SysCacheGetAttr(), transformExpr(), and Query::utilityStmt.

Referenced by transformStmt().

◆ transformCreateTableAsStmt()

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

Definition at line 2997 of file analyze.c.

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

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

2853 {
2854  Query *result;
2855  Query *query;
2856 
2857  if ((stmt->options & CURSOR_OPT_SCROLL) &&
2858  (stmt->options & CURSOR_OPT_NO_SCROLL))
2859  ereport(ERROR,
2860  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2861  /* translator: %s is a SQL keyword */
2862  errmsg("cannot specify both %s and %s",
2863  "SCROLL", "NO SCROLL")));
2864 
2865  if ((stmt->options & CURSOR_OPT_ASENSITIVE) &&
2866  (stmt->options & CURSOR_OPT_INSENSITIVE))
2867  ereport(ERROR,
2868  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2869  /* translator: %s is a SQL keyword */
2870  errmsg("cannot specify both %s and %s",
2871  "ASENSITIVE", "INSENSITIVE")));
2872 
2873  /* Transform contained query, not allowing SELECT INTO */
2874  query = transformStmt(pstate, stmt->query);
2875  stmt->query = (Node *) query;
2876 
2877  /* Grammar should not have allowed anything but SELECT */
2878  if (!IsA(query, Query) ||
2879  query->commandType != CMD_SELECT)
2880  elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR");
2881 
2882  /*
2883  * We also disallow data-modifying WITH in a cursor. (This could be
2884  * allowed, but the semantics of when the updates occur might be
2885  * surprising.)
2886  */
2887  if (query->hasModifyingCTE)
2888  ereport(ERROR,
2889  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2890  errmsg("DECLARE CURSOR must not contain data-modifying statements in WITH")));
2891 
2892  /* FOR UPDATE and WITH HOLD are not compatible */
2893  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
2894  ereport(ERROR,
2895  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2896  /*------
2897  translator: %s is a SQL row locking clause such as FOR UPDATE */
2898  errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
2900  linitial(query->rowMarks))->strength)),
2901  errdetail("Holdable cursors must be READ ONLY.")));
2902 
2903  /* FOR UPDATE and SCROLL are not compatible */
2904  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
2905  ereport(ERROR,
2906  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2907  /*------
2908  translator: %s is a SQL row locking clause such as FOR UPDATE */
2909  errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
2911  linitial(query->rowMarks))->strength)),
2912  errdetail("Scrollable cursors must be READ ONLY.")));
2913 
2914  /* FOR UPDATE and INSENSITIVE are not compatible */
2915  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
2916  ereport(ERROR,
2917  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2918  /*------
2919  translator: %s is a SQL row locking clause such as FOR UPDATE */
2920  errmsg("DECLARE INSENSITIVE CURSOR ... %s is not valid",
2922  linitial(query->rowMarks))->strength)),
2923  errdetail("Insensitive cursors must be READ ONLY.")));
2924 
2925  /* represent the command as a utility Query */
2926  result = makeNode(Query);
2927  result->commandType = CMD_UTILITY;
2928  result->utilityStmt = (Node *) stmt;
2929 
2930  return result;
2931 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
@ CMD_SELECT
Definition: nodes.h:276
#define CURSOR_OPT_INSENSITIVE
Definition: parsenodes.h:3158
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:3156
#define CURSOR_OPT_HOLD
Definition: parsenodes.h:3160
#define CURSOR_OPT_ASENSITIVE
Definition: parsenodes.h:3159
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:3157
#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 511 of file analyze.c.

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

References ACL_DELETE, assign_query_collations(), CMD_DELETE, Query::commandType, Query::cteList, Query::distinctClause, 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 2945 of file analyze.c.

2946 {
2947  Query *result;
2948  bool generic_plan = false;
2949  Oid *paramTypes = NULL;
2950  int numParams = 0;
2951 
2952  /*
2953  * If we have no external source of parameter definitions, and the
2954  * GENERIC_PLAN option is specified, then accept variable parameter
2955  * definitions (similarly to PREPARE, for example).
2956  */
2957  if (pstate->p_paramref_hook == NULL)
2958  {
2959  ListCell *lc;
2960 
2961  foreach(lc, stmt->options)
2962  {
2963  DefElem *opt = (DefElem *) lfirst(lc);
2964 
2965  if (strcmp(opt->defname, "generic_plan") == 0)
2966  generic_plan = defGetBoolean(opt);
2967  /* don't "break", as we want the last value */
2968  }
2969  if (generic_plan)
2970  setup_parse_variable_parameters(pstate, &paramTypes, &numParams);
2971  }
2972 
2973  /* transform contained query, allowing SELECT INTO */
2974  stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
2975 
2976  /* make sure all is well with parameter types */
2977  if (generic_plan)
2978  check_variable_parameters(pstate, (Query *) stmt->query);
2979 
2980  /* represent the command as a utility Query */
2981  result = makeNode(Query);
2982  result->commandType = CMD_UTILITY;
2983  result->utilityStmt = (Node *) stmt;
2984 
2985  return result;
2986 }
bool defGetBoolean(DefElem *def)
Definition: define.c:108
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:275
char * defname
Definition: parsenodes.h:809
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:236

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

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

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

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

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

Referenced by transformStmt().

◆ transformLockingClause()

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

Definition at line 3286 of file analyze.c.

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

References ACL_SELECT_FOR_UPDATE, RangeTblEntry::alias, Alias::aliasname, applyLockingClause(), RangeVar::catalogname, CheckSelectLocking(), elog(), RangeTblEntry::eref, ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, getRTEPermissionInfo(), i, RangeTblEntry::inFromCl, RangeTblEntry::join_using_alias, 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 1108 of file analyze.c.

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

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, RangeTblEntry::relkind, RowExclusiveLock, OnConflictClause::targetList, transformOnConflictArbiter(), transformUpdateTargetList(), transformWhereClause(), and OnConflictClause::whereClause.

◆ transformOptionalSelectInto()

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

Definition at line 275 of file analyze.c.

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

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

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

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

Definition at line 2545 of file analyze.c.

2546 {
2547  List *rlist;
2548  int save_next_resno;
2549 
2550  if (returningList == NIL)
2551  return NIL; /* nothing to do */
2552 
2553  /*
2554  * We need to assign resnos starting at one in the RETURNING list. Save
2555  * and restore the main tlist's value of p_next_resno, just in case
2556  * someone looks at it later (probably won't happen).
2557  */
2558  save_next_resno = pstate->p_next_resno;
2559  pstate->p_next_resno = 1;
2560 
2561  /* transform RETURNING identically to a SELECT targetlist */
2562  rlist = transformTargetList(pstate, returningList, EXPR_KIND_RETURNING);
2563 
2564  /*
2565  * Complain if the nonempty tlist expanded to nothing (which is possible
2566  * if it contains only a star-expansion of a zero-column table). If we
2567  * allow this, the parsed Query will look like it didn't have RETURNING,
2568  * with results that would probably surprise the user.
2569  */
2570  if (rlist == NIL)
2571  ereport(ERROR,
2572  (errcode(ERRCODE_SYNTAX_ERROR),
2573  errmsg("RETURNING must have at least one column"),
2574  parser_errposition(pstate,
2575  exprLocation(linitial(returningList)))));
2576 
2577  /* mark column origins */
2578  markTargetListOrigins(pstate, rlist);
2579 
2580  /* resolve any still-unresolved output columns as being type text */
2581  if (pstate->p_resolve_unknowns)
2582  resolveTargetListUnknowns(pstate, rlist);
2583 
2584  /* restore state */
2585  pstate->p_next_resno = save_next_resno;
2586 
2587  return rlist;
2588 }
@ EXPR_KIND_RETURNING
Definition: parse_node.h:64
void resolveTargetListUnknowns(ParseState *pstate, List *targetlist)
Definition: parse_target.c:289
void markTargetListOrigins(ParseState *pstate, List *targetlist)
Definition: parse_target.c:319
int p_next_resno
Definition: parse_node.h:211

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

Referenced by transformDeleteStmt(), and transformUpdateStmt().

◆ transformReturnStmt()

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

Definition at line 2377 of file analyze.c.

2378 {
2379  Query *qry = makeNode(Query);
2380 
2381  qry->commandType = CMD_SELECT;
2382  qry->isReturn = true;
2383 
2385  1, NULL, false));
2386 
2387  if (pstate->p_resolve_unknowns)
2388  resolveTargetListUnknowns(pstate, qry->targetList);
2389  qry->rtable = pstate->p_rtable;
2390  qry->rteperminfos = pstate->p_rteperminfos;
2391  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
2392  qry->hasSubLinks = pstate->p_hasSubLinks;
2393  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
2394  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2395  qry->hasAggs = pstate->p_hasAggs;
2396 
2397  assign_query_collations(pstate, qry);
2398 
2399  return qry;
2400 }

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

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

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

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

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

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

References addRangeTableEntryForSubquery(), SetOperationStmt::all, Assert(), cancel_parser_errposition_callback(), check_stack_depth(), coerce_to_common_type(), contain_vars_of_level(), 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 314 of file analyze.c.

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

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

252 {
253  Query *result;
254 
255  /* We're at top level, so allow SELECT INTO */
256  result = transformOptionalSelectInto(pstate, parseTree->stmt);
257 
258  result->stmt_location = parseTree->stmt_location;
259  result->stmt_len = parseTree->stmt_len;
260 
261  return result;
262 }
int stmt_location
Definition: parsenodes.h:235
int stmt_len
Definition: parsenodes.h:1887
int stmt_location
Definition: parsenodes.h:1886

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

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

References ACL_UPDATE, assign_query_collations(), CMD_UPDATE, Query::commandType, Query::cteList, 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 2473 of file analyze.c.

2474 {
2475  List *tlist = NIL;
2476  RTEPermissionInfo *target_perminfo;
2477  ListCell *orig_tl;
2478  ListCell *tl;
2479 
2480  tlist = transformTargetList(pstate, origTlist,
2482 
2483  /* Prepare to assign non-conflicting resnos to resjunk attributes */
2486 
2487  /* Prepare non-junk columns for assignment to target table */
2488  target_perminfo = pstate->p_target_nsitem->p_perminfo;
2489  orig_tl = list_head(origTlist);
2490 
2491  foreach(tl, tlist)
2492  {
2493  TargetEntry *tle = (TargetEntry *) lfirst(tl);
2494  ResTarget *origTarget;
2495  int attrno;
2496 
2497  if (tle->resjunk)
2498  {
2499  /*
2500  * Resjunk nodes need no additional processing, but be sure they
2501  * have resnos that do not match any target columns; else rewriter
2502  * or planner might get confused. They don't need a resname
2503  * either.
2504  */
2505  tle->resno = (AttrNumber) pstate->p_next_resno++;
2506  tle->resname = NULL;
2507  continue;
2508  }
2509  if (orig_tl == NULL)
2510  elog(ERROR, "UPDATE target count mismatch --- internal error");
2511  origTarget = lfirst_node(ResTarget, orig_tl);
2512 
2513  attrno = attnameAttNum(pstate->p_target_relation,
2514  origTarget->name, true);
2515  if (attrno == InvalidAttrNumber)
2516  ereport(ERROR,
2517  (errcode(ERRCODE_UNDEFINED_COLUMN),
2518  errmsg("column \"%s\" of relation \"%s\" does not exist",
2519  origTarget->name,
2521  parser_errposition(pstate, origTarget->location)));
2522 
2523  updateTargetListEntry(pstate, tle, origTarget->name,
2524  attrno,
2525  origTarget->indirection,
2526  origTarget->location);
2527 
2528  /* Mark the target column as requiring update permissions */
2529  target_perminfo->updatedCols = bms_add_member(target_perminfo->updatedCols,
2531 
2532  orig_tl = lnext(origTlist, orig_tl);
2533  }
2534  if (orig_tl != NULL)
2535  elog(ERROR, "UPDATE target count mismatch --- internal error");
2536 
2537  return tlist;
2538 }
@ 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:620
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
#define RelationGetRelationName(relation)
Definition: rel.h:538
Bitmapset * updatedCols
Definition: parsenodes.h:1249

References attnameAttNum(), bms_add_member(), elog(), ereport, errcode(), errmsg(), ERROR, EXPR_KIND_UPDATE_SOURCE, FirstLowInvalidHeapAttributeNumber, ResTarget::indirection, InvalidAttrNumber, lfirst, lfirst_node, list_head(), lnext(), ResTarget::location, ResTarget::name, NIL, ParseState::p_next_resno, 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 1470 of file analyze.c.

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