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

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

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:1619
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:234
#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 3225 of file analyze.c.

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

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:158
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
@ RTE_SUBQUERY
Definition: parsenodes.h:1007
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:181
Query * subquery
Definition: parsenodes.h:1073
RTEKind rtekind
Definition: parsenodes.h:1025
Expr * expr
Definition: primnodes.h:1922
AttrNumber varattno
Definition: primnodes.h:246
int varno
Definition: primnodes.h:241
Index varlevelsup
Definition: primnodes.h:266

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:518
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 3200 of file analyze.c.

3201 {
3202  switch (strength)
3203  {
3204  case LCS_NONE:
3205  Assert(false);
3206  break;
3207  case LCS_FORKEYSHARE:
3208  return "FOR KEY SHARE";
3209  case LCS_FORSHARE:
3210  return "FOR SHARE";
3211  case LCS_FORNOKEYUPDATE:
3212  return "FOR NO KEY UPDATE";
3213  case LCS_FORUPDATE:
3214  return "FOR UPDATE";
3215  }
3216  return "FOR some"; /* shouldn't happen */
3217 }
@ 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:180
unsigned int Oid
Definition: postgres_ext.h:31
Index tleSortGroupRef
Definition: parsenodes.h:1385

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:1861

References nodeTag, and RawStmt::stmt.

Referenced by analyze_requires_snapshot().

◆ transformCallStmt()

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

Definition at line 3075 of file analyze.c.

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

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

Referenced by transformStmt().

◆ transformCreateTableAsStmt()

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

Definition at line 3000 of file analyze.c.

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

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

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

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

2949 {
2950  Query *result;
2951  bool generic_plan = false;
2952  Oid *paramTypes = NULL;
2953  int numParams = 0;
2954 
2955  /*
2956  * If we have no external source of parameter definitions, and the
2957  * GENERIC_PLAN option is specified, then accept variable parameter
2958  * definitions (similarly to PREPARE, for example).
2959  */
2960  if (pstate->p_paramref_hook == NULL)
2961  {
2962  ListCell *lc;
2963 
2964  foreach(lc, stmt->options)
2965  {
2966  DefElem *opt = (DefElem *) lfirst(lc);
2967 
2968  if (strcmp(opt->defname, "generic_plan") == 0)
2969  generic_plan = defGetBoolean(opt);
2970  /* don't "break", as we want the last value */
2971  }
2972  if (generic_plan)
2973  setup_parse_variable_parameters(pstate, &paramTypes, &numParams);
2974  }
2975 
2976  /* transform contained query, allowing SELECT INTO */
2977  stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
2978 
2979  /* make sure all is well with parameter types */
2980  if (generic_plan)
2981  check_variable_parameters(pstate, (Query *) stmt->query);
2982 
2983  /* represent the command as a utility Query */
2984  result = makeNode(Query);
2985  result->commandType = CMD_UTILITY;
2986  result->utilityStmt = (Node *) stmt;
2987 
2988  return result;
2989 }
bool defGetBoolean(DefElem *def)
Definition: define.c:108
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:275
char * defname
Definition: parsenodes.h:802
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:1322
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:563
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
List * newvals
Definition: primnodes.h:1095
int location
Definition: parsenodes.h:510
List * indirection
Definition: parsenodes.h:508
char * name
Definition: parsenodes.h:507
Expr * refassgnexpr
Definition: primnodes.h:638

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:828
long val
Definition: informix.c:664
List * lappend_int(List *list, int datum)
Definition: list.c:357
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c: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:409
@ CMD_INSERT
Definition: nodes.h:257
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:74
#define ACL_INSERT
Definition: parsenodes.h:76
#define ACL_UPDATE
Definition: parsenodes.h:78
static OnConflictExpr * transformOnConflictClause(ParseState *pstate, OnConflictClause *onConflictClause)
Definition: analyze.c: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:186
List * sortClause
Definition: parsenodes.h:1986
IntoClause * intoClause
Definition: parsenodes.h:1963
Node * limitOffset
Definition: parsenodes.h:1987
List * lockingClause
Definition: parsenodes.h:1990
Node * limitCount
Definition: parsenodes.h:1988
List * valuesLists
Definition: parsenodes.h:1980
WithClause * withClause
Definition: parsenodes.h:1991
int location
Definition: primnodes.h:279
#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 3289 of file analyze.c.

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

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:957
#define RowExclusiveLock
Definition: lockdefs.h:38
void transformOnConflictArbiter(ParseState *pstate, OnConflictClause *onConflictClause, List **arbiterExpr, Node **arbiterWhere, Oid *constraint)
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
List * transformUpdateTargetList(ParseState *pstate, List *origTlist)
Definition: analyze.c:2473
List * BuildOnConflictExcludedTargetlist(Relation targetrel, Index exclRelIndex)
Definition: analyze.c:1215
#define llast(l)
Definition: pg_list.h:198
OnConflictAction action
Definition: parsenodes.h:1572
List * arbiterElems
Definition: primnodes.h:2059
OnConflictAction action
Definition: primnodes.h:2056
List * onConflictSet
Definition: primnodes.h:2065
List * exclRelTlist
Definition: primnodes.h:2068
Node * onConflictWhere
Definition: primnodes.h:2066
Node * arbiterWhere
Definition: primnodes.h:2061
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:1948
@ OBJECT_TABLE
Definition: parsenodes.h:2137
IntoClause * into
Definition: parsenodes.h:3733
ObjectType objtype
Definition: parsenodes.h:3734

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

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

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

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:631
void * palloc0(Size size)
Definition: mcxt.c:1232
@ JOIN_INNER
Definition: nodes.h:283
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:575
#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:1998
SetOperation op
Definition: parsenodes.h:1996
AttrNumber resno
Definition: primnodes.h:1924
bool recursive
Definition: parsenodes.h:1544

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:1950
@ SETOP_UNION
Definition: parsenodes.h:1949
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:2026
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:36
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:2606
static Query * transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
Definition: analyze.c:3000
static Query * transformCallStmt(ParseState *pstate, CallStmt *stmt)
Definition: analyze.c:3075
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:2948
static Query * transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
Definition: analyze.c:2855
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:228
int stmt_len
Definition: parsenodes.h:1863
int stmt_location
Definition: parsenodes.h:1862

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:256

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  (origTarget->indirection != NIL &&
2522  strcmp(origTarget->name, pstate->p_target_nsitem->p_names->aliasname) == 0) ?
2523  errhint("SET target columns cannot be qualified with the relation name.") : 0,
2524  parser_errposition(pstate, origTarget->location)));
2525 
2526  updateTargetListEntry(pstate, tle, origTarget->name,
2527  attrno,
2528  origTarget->indirection,
2529  origTarget->location);
2530 
2531  /* Mark the target column as requiring update permissions */
2532  target_perminfo->updatedCols = bms_add_member(target_perminfo->updatedCols,
2534 
2535  orig_tl = lnext(origTlist, orig_tl);
2536  }
2537  if (orig_tl != NULL)
2538  elog(ERROR, "UPDATE target count mismatch --- internal error");
2539 
2540  return tlist;
2541 }
@ 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:1242

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

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

◆ transformValuesClause()

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

Definition at line 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:1546
List * expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem, int sublevels_up, bool require_col_privs, int location)

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

Referenced by transformStmt().

Variable Documentation

◆ post_parse_analyze_hook