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

432 {
433  bool result;
434 
435  switch (nodeTag(parseTree->stmt))
436  {
437  /*
438  * Optimizable statements
439  */
440  case T_InsertStmt:
441  case T_DeleteStmt:
442  case T_UpdateStmt:
443  case T_MergeStmt:
444  case T_SelectStmt:
445  case T_PLAssignStmt:
446  result = true;
447  break;
448 
449  /*
450  * Special cases
451  */
452  case T_DeclareCursorStmt:
453  case T_ExplainStmt:
454  case T_CreateTableAsStmt:
455  /* yes, because we must analyze the contained statement */
456  result = true;
457  break;
458 
459  default:
460  /* other utility statements don't have any real parse analysis */
461  result = false;
462  break;
463  }
464 
465  return result;
466 }
#define nodeTag(nodeptr)
Definition: nodes.h:133
Node * stmt
Definition: parsenodes.h:1847

References nodeTag, and RawStmt::stmt.

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

3478 {
3479  RowMarkClause *rc;
3480 
3481  Assert(strength != LCS_NONE); /* else caller error */
3482 
3483  /* If it's an explicit clause, make sure hasForUpdate gets set */
3484  if (!pushedDown)
3485  qry->hasForUpdate = true;
3486 
3487  /* Check for pre-existing entry for same rtindex */
3488  if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
3489  {
3490  /*
3491  * If the same RTE is specified with more than one locking strength,
3492  * use the strongest. (Reasonable, since you can't take both a shared
3493  * and exclusive lock at the same time; it'll end up being exclusive
3494  * anyway.)
3495  *
3496  * Similarly, if the same RTE is specified with more than one lock
3497  * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
3498  * turn wins over waiting for the lock (the default). This is a bit
3499  * more debatable but raising an error doesn't seem helpful. (Consider
3500  * for instance SELECT FOR UPDATE NOWAIT from a view that internally
3501  * contains a plain FOR UPDATE spec.) Having NOWAIT win over SKIP
3502  * LOCKED is reasonable since the former throws an error in case of
3503  * coming across a locked tuple, which may be undesirable in some
3504  * cases but it seems better than silently returning inconsistent
3505  * results.
3506  *
3507  * And of course pushedDown becomes false if any clause is explicit.
3508  */
3509  rc->strength = Max(rc->strength, strength);
3510  rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
3511  rc->pushedDown &= pushedDown;
3512  return;
3513  }
3514 
3515  /* Make a new RowMarkClause */
3516  rc = makeNode(RowMarkClause);
3517  rc->rti = rtindex;
3518  rc->strength = strength;
3519  rc->waitPolicy = waitPolicy;
3520  rc->pushedDown = pushedDown;
3521  qry->rowMarks = lappend(qry->rowMarks, rc);
3522 }
#define Max(x, y)
Definition: c.h:982
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:338
@ LCS_NONE
Definition: lockoptions.h:23
#define makeNode(_type_)
Definition: nodes.h:176
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
List * rowMarks
Definition: parsenodes.h:215
LockClauseStrength strength
Definition: parsenodes.h:1534
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1535

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

1179 {
1180  List *result = NIL;
1181  int attno;
1182  Var *var;
1183  TargetEntry *te;
1184 
1185  /*
1186  * Note that resnos of the tlist must correspond to attnos of the
1187  * underlying relation, hence we need entries for dropped columns too.
1188  */
1189  for (attno = 0; attno < RelationGetNumberOfAttributes(targetrel); attno++)
1190  {
1191  Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno);
1192  char *name;
1193 
1194  if (attr->attisdropped)
1195  {
1196  /*
1197  * can't use atttypid here, but it doesn't really matter what type
1198  * the Const claims to be.
1199  */
1200  var = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
1201  name = NULL;
1202  }
1203  else
1204  {
1205  var = makeVar(exclRelIndex, attno + 1,
1206  attr->atttypid, attr->atttypmod,
1207  attr->attcollation,
1208  0);
1209  name = pstrdup(NameStr(attr->attname));
1210  }
1211 
1212  te = makeTargetEntry((Expr *) var,
1213  attno + 1,
1214  name,
1215  false);
1216 
1217  result = lappend(result, te);
1218  }
1219 
1220  /*
1221  * Add a whole-row-Var entry to support references to "EXCLUDED.*". Like
1222  * the other entries in the EXCLUDED tlist, its resno must match the Var's
1223  * varattno, else the wrong things happen while resolving references in
1224  * setrefs.c. This is against normal conventions for targetlists, but
1225  * it's okay since we don't use this as a real tlist.
1226  */
1227  var = makeVar(exclRelIndex, InvalidAttrNumber,
1228  targetrel->rd_rel->reltype,
1229  -1, InvalidOid, 0);
1230  te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
1231  result = lappend(result, te);
1232 
1233  return result;
1234 }
#define InvalidAttrNumber
Definition: attnum.h:23
#define NameStr(name)
Definition: c.h:730
const char * name
Definition: encode.c:571
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:1624
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:509
Definition: pg_list.h:54
TupleDesc rd_att
Definition: rel.h:111
Form_pg_class rd_rel
Definition: rel.h:110
Definition: primnodes.h:226
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

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

3185 {
3186  Assert(strength != LCS_NONE); /* else caller error */
3187 
3188  if (qry->setOperations)
3189  ereport(ERROR,
3190  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3191  /*------
3192  translator: %s is a SQL row locking clause such as FOR UPDATE */
3193  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
3194  LCS_asString(strength))));
3195  if (qry->distinctClause != NIL)
3196  ereport(ERROR,
3197  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3198  /*------
3199  translator: %s is a SQL row locking clause such as FOR UPDATE */
3200  errmsg("%s is not allowed with DISTINCT clause",
3201  LCS_asString(strength))));
3202  if (qry->groupClause != NIL || qry->groupingSets != NIL)
3203  ereport(ERROR,
3204  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3205  /*------
3206  translator: %s is a SQL row locking clause such as FOR UPDATE */
3207  errmsg("%s is not allowed with GROUP BY clause",
3208  LCS_asString(strength))));
3209  if (qry->havingQual != NULL)
3210  ereport(ERROR,
3211  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3212  /*------
3213  translator: %s is a SQL row locking clause such as FOR UPDATE */
3214  errmsg("%s is not allowed with HAVING clause",
3215  LCS_asString(strength))));
3216  if (qry->hasAggs)
3217  ereport(ERROR,
3218  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3219  /*------
3220  translator: %s is a SQL row locking clause such as FOR UPDATE */
3221  errmsg("%s is not allowed with aggregate functions",
3222  LCS_asString(strength))));
3223  if (qry->hasWindowFuncs)
3224  ereport(ERROR,
3225  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3226  /*------
3227  translator: %s is a SQL row locking clause such as FOR UPDATE */
3228  errmsg("%s is not allowed with window functions",
3229  LCS_asString(strength))));
3230  if (qry->hasTargetSRFs)
3231  ereport(ERROR,
3232  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3233  /*------
3234  translator: %s is a SQL row locking clause such as FOR UPDATE */
3235  errmsg("%s is not allowed with set-returning functions in the target list",
3236  LCS_asString(strength))));
3237 }
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:3159
Node * setOperations
Definition: parsenodes.h:217
List * groupClause
Definition: parsenodes.h:198
Node * havingQual
Definition: parsenodes.h:203
List * groupingSets
Definition: parsenodes.h:201
List * distinctClause
Definition: parsenodes.h:207

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

1248 {
1249  if (expr == NULL)
1250  return -1;
1251  if (IsA(expr, RowExpr))
1252  return list_length(((RowExpr *) expr)->args);
1253  if (IsA(expr, Var))
1254  {
1255  Var *var = (Var *) expr;
1256  AttrNumber attnum = var->varattno;
1257 
1258  if (attnum > 0 && var->vartype == RECORDOID)
1259  {
1260  RangeTblEntry *rte;
1261 
1262  rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup);
1263  if (rte->rtekind == RTE_SUBQUERY)
1264  {
1265  /* Subselect-in-FROM: examine sub-select's output expr */
1267  attnum);
1268 
1269  if (ste == NULL || ste->resjunk)
1270  return -1;
1271  expr = (Node *) ste->expr;
1272  if (IsA(expr, RowExpr))
1273  return list_length(((RowExpr *) expr)->args);
1274  }
1275  }
1276  }
1277  return -1;
1278 }
int16 AttrNumber
Definition: attnum.h:21
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
RangeTblEntry * GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up)
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
@ RTE_SUBQUERY
Definition: parsenodes.h:1015
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:189
Query * subquery
Definition: parsenodes.h:1081
RTEKind rtekind
Definition: parsenodes.h:1033
Expr * expr
Definition: primnodes.h:1842
AttrNumber varattno
Definition: primnodes.h:238
int varno
Definition: primnodes.h:233
Index varlevelsup
Definition: primnodes.h:258

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

Referenced by transformInsertRow().

◆ determineRecursiveColTypes()

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

Definition at line 2285 of file analyze.c.

2286 {
2287  Node *node;
2288  int leftmostRTI;
2289  Query *leftmostQuery;
2290  List *targetList;
2291  ListCell *left_tlist;
2292  ListCell *nrtl;
2293  int next_resno;
2294 
2295  /*
2296  * Find leftmost leaf SELECT
2297  */
2298  node = larg;
2299  while (node && IsA(node, SetOperationStmt))
2300  node = ((SetOperationStmt *) node)->larg;
2301  Assert(node && IsA(node, RangeTblRef));
2302  leftmostRTI = ((RangeTblRef *) node)->rtindex;
2303  leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
2304  Assert(leftmostQuery != NULL);
2305 
2306  /*
2307  * Generate dummy targetlist using column names of leftmost select and
2308  * dummy result expressions of the non-recursive term.
2309  */
2310  targetList = NIL;
2311  next_resno = 1;
2312 
2313  forboth(nrtl, nrtargetlist, left_tlist, leftmostQuery->targetList)
2314  {
2315  TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
2316  TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
2317  char *colName;
2318  TargetEntry *tle;
2319 
2320  Assert(!lefttle->resjunk);
2321  colName = pstrdup(lefttle->resname);
2322  tle = makeTargetEntry(nrtle->expr,
2323  next_resno++,
2324  colName,
2325  false);
2326  targetList = lappend(targetList, tle);
2327  }
2328 
2329  /* Now build CTE's output column info using dummy targetlist */
2330  analyzeCTETargetList(pstate, pstate->p_parent_cte, targetList);
2331 }
void analyzeCTETargetList(ParseState *pstate, CommonTableExpr *cte, List *tlist)
Definition: parse_cte.c:576
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define lfirst(lc)
Definition: pg_list.h:172
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:467
CommonTableExpr * p_parent_cte
Definition: parse_node.h:205
List * p_rtable
Definition: parse_node.h:193

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

Referenced by transformSetOperationTree().

◆ LCS_asString()

const char* LCS_asString ( LockClauseStrength  strength)

Definition at line 3159 of file analyze.c.

3160 {
3161  switch (strength)
3162  {
3163  case LCS_NONE:
3164  Assert(false);
3165  break;
3166  case LCS_FORKEYSHARE:
3167  return "FOR KEY SHARE";
3168  case LCS_FORSHARE:
3169  return "FOR SHARE";
3170  case LCS_FORNOKEYUPDATE:
3171  return "FOR NO KEY UPDATE";
3172  case LCS_FORUPDATE:
3173  return "FOR UPDATE";
3174  }
3175  return "FOR some"; /* shouldn't happen */
3176 }
@ 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 1907 of file analyze.c.

1908 {
1910  Oid sortop;
1911  Oid eqop;
1912  bool hashable;
1913 
1914  /* determine the eqop and optional sortop */
1915  get_sort_group_operators(rescoltype,
1916  false, true, false,
1917  &sortop, &eqop, NULL,
1918  &hashable);
1919 
1920  /*
1921  * The type cache doesn't believe that record is hashable (see
1922  * cache_record_field_properties()), but if the caller really needs hash
1923  * support, we can assume it does. Worst case, if any components of the
1924  * record don't support hashing, we will fail at execution.
1925  */
1926  if (require_hash && (rescoltype == RECORDOID || rescoltype == RECORDARRAYOID))
1927  hashable = true;
1928 
1929  /* we don't have a tlist yet, so can't assign sortgrouprefs */
1930  grpcl->tleSortGroupRef = 0;
1931  grpcl->eqop = eqop;
1932  grpcl->sortop = sortop;
1933  grpcl->nulls_first = false; /* OK with or without sortop */
1934  grpcl->hashable = hashable;
1935 
1936  return grpcl;
1937 }
void get_sort_group_operators(Oid argtype, bool needLT, bool needEQ, bool needGT, Oid *ltOpr, Oid *eqOpr, Oid *gtOpr, bool *isHashable)
Definition: parse_oper.c:192
unsigned int Oid
Definition: postgres_ext.h:31
Index tleSortGroupRef
Definition: parsenodes.h:1393

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, sourceText);
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, const char *querytext)
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, sourceText);
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, sourceText);
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().

◆ transformCallStmt()

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

Definition at line 3034 of file analyze.c.

3035 {
3036  List *targs;
3037  ListCell *lc;
3038  Node *node;
3039  FuncExpr *fexpr;
3040  HeapTuple proctup;
3041  Datum proargmodes;
3042  bool isNull;
3043  List *outargs = NIL;
3044  Query *result;
3045 
3046  /*
3047  * First, do standard parse analysis on the procedure call and its
3048  * arguments, allowing us to identify the called procedure.
3049  */
3050  targs = NIL;
3051  foreach(lc, stmt->funccall->args)
3052  {
3053  targs = lappend(targs, transformExpr(pstate,
3054  (Node *) lfirst(lc),
3056  }
3057 
3058  node = ParseFuncOrColumn(pstate,
3059  stmt->funccall->funcname,
3060  targs,
3061  pstate->p_last_srf,
3062  stmt->funccall,
3063  true,
3064  stmt->funccall->location);
3065 
3066  assign_expr_collations(pstate, node);
3067 
3068  fexpr = castNode(FuncExpr, node);
3069 
3070  proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid));
3071  if (!HeapTupleIsValid(proctup))
3072  elog(ERROR, "cache lookup failed for function %u", fexpr->funcid);
3073 
3074  /*
3075  * Expand the argument list to deal with named-argument notation and
3076  * default arguments. For ordinary FuncExprs this'd be done during
3077  * planning, but a CallStmt doesn't go through planning, and there seems
3078  * no good reason not to do it here.
3079  */
3080  fexpr->args = expand_function_arguments(fexpr->args,
3081  true,
3082  fexpr->funcresulttype,
3083  proctup);
3084 
3085  /* Fetch proargmodes; if it's null, there are no output args */
3086  proargmodes = SysCacheGetAttr(PROCOID, proctup,
3087  Anum_pg_proc_proargmodes,
3088  &isNull);
3089  if (!isNull)
3090  {
3091  /*
3092  * Split the list into input arguments in fexpr->args and output
3093  * arguments in stmt->outargs. INOUT arguments appear in both lists.
3094  */
3095  ArrayType *arr;
3096  int numargs;
3097  char *argmodes;
3098  List *inargs;
3099  int i;
3100 
3101  arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
3102  numargs = list_length(fexpr->args);
3103  if (ARR_NDIM(arr) != 1 ||
3104  ARR_DIMS(arr)[0] != numargs ||
3105  ARR_HASNULL(arr) ||
3106  ARR_ELEMTYPE(arr) != CHAROID)
3107  elog(ERROR, "proargmodes is not a 1-D char array of length %d or it contains nulls",
3108  numargs);
3109  argmodes = (char *) ARR_DATA_PTR(arr);
3110 
3111  inargs = NIL;
3112  i = 0;
3113  foreach(lc, fexpr->args)
3114  {
3115  Node *n = lfirst(lc);
3116 
3117  switch (argmodes[i])
3118  {
3119  case PROARGMODE_IN:
3120  case PROARGMODE_VARIADIC:
3121  inargs = lappend(inargs, n);
3122  break;
3123  case PROARGMODE_OUT:
3124  outargs = lappend(outargs, n);
3125  break;
3126  case PROARGMODE_INOUT:
3127  inargs = lappend(inargs, n);
3128  outargs = lappend(outargs, copyObject(n));
3129  break;
3130  default:
3131  /* note we don't support PROARGMODE_TABLE */
3132  elog(ERROR, "invalid argmode %c for procedure",
3133  argmodes[i]);
3134  break;
3135  }
3136  i++;
3137  }
3138  fexpr->args = inargs;
3139  }
3140 
3141  stmt->funcexpr = fexpr;
3142  stmt->outargs = outargs;
3143 
3144  ReleaseSysCache(proctup);
3145 
3146  /* represent the command as a utility Query */
3147  result = makeNode(Query);
3148  result->commandType = CMD_UTILITY;
3149  result->utilityStmt = (Node *) stmt;
3150 
3151  return result;
3152 }
#define ARR_NDIM(a)
Definition: array.h:283
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define DatumGetArrayTypeP(X)
Definition: array.h:254
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_HASNULL(a)
Definition: array.h:284
List * expand_function_arguments(List *args, bool include_out_arguments, Oid result_type, HeapTuple func_tuple)
Definition: clauses.c:4056
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define stmt
Definition: indent_codes.h:59
int i
Definition: isn.c:73
#define copyObject(obj)
Definition: nodes.h:244
@ CMD_UTILITY
Definition: nodes.h:281
#define castNode(_type_, nodeptr)
Definition: nodes.h:197
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:104
Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *last_srf, FuncCall *fn, bool proc_call, int location)
Definition: parse_func.c:90
@ EXPR_KIND_CALL_ARGUMENT
Definition: parse_node.h:80
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
Oid funcid
Definition: primnodes.h:677
List * args
Definition: primnodes.h:695
Node * p_last_srf
Definition: parse_node.h:228
CmdType commandType
Definition: parsenodes.h:128
Node * utilityStmt
Definition: parsenodes.h:143
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:866
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:818
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1079
@ PROCOID
Definition: syscache.h:79

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

Referenced by transformStmt().

◆ transformCreateTableAsStmt()

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

Definition at line 2959 of file analyze.c.

2960 {
2961  Query *result;
2962  Query *query;
2963 
2964  /* transform contained query, not allowing SELECT INTO */
2965  query = transformStmt(pstate, stmt->query);
2966  stmt->query = (Node *) query;
2967 
2968  /* additional work needed for CREATE MATERIALIZED VIEW */
2969  if (stmt->objtype == OBJECT_MATVIEW)
2970  {
2971  /*
2972  * Prohibit a data-modifying CTE in the query used to create a
2973  * materialized view. It's not sufficiently clear what the user would
2974  * want to happen if the MV is refreshed or incrementally maintained.
2975  */
2976  if (query->hasModifyingCTE)
2977  ereport(ERROR,
2978  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2979  errmsg("materialized views must not use data-modifying statements in WITH")));
2980 
2981  /*
2982  * Check whether any temporary database objects are used in the
2983  * creation query. It would be hard to refresh data or incrementally
2984  * maintain it if a source disappeared.
2985  */
2986  if (isQueryUsingTempRelation(query))
2987  ereport(ERROR,
2988  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2989  errmsg("materialized views must not use temporary tables or views")));
2990 
2991  /*
2992  * A materialized view would either need to save parameters for use in
2993  * maintaining/loading the data or prohibit them entirely. The latter
2994  * seems safer and more sane.
2995  */
2996  if (query_contains_extern_params(query))
2997  ereport(ERROR,
2998  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2999  errmsg("materialized views may not be defined using bound parameters")));
3000 
3001  /*
3002  * For now, we disallow unlogged materialized views, because it seems
3003  * like a bad idea for them to just go to empty after a crash. (If we
3004  * could mark them as unpopulated, that would be better, but that
3005  * requires catalog changes which crash recovery can't presently
3006  * handle.)
3007  */
3008  if (stmt->into->rel->relpersistence == RELPERSISTENCE_UNLOGGED)
3009  ereport(ERROR,
3010  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3011  errmsg("materialized views cannot be unlogged")));
3012 
3013  /*
3014  * At runtime, we'll need a copy of the parsed-but-not-rewritten Query
3015  * for purposes of creating the view's ON SELECT rule. We stash that
3016  * in the IntoClause because that's where intorel_startup() can
3017  * conveniently get it from.
3018  */
3019  stmt->into->viewQuery = (Node *) copyObject(query);
3020  }
3021 
3022  /* represent the command as a utility Query */
3023  result = makeNode(Query);
3024  result->commandType = CMD_UTILITY;
3025  result->utilityStmt = (Node *) stmt;
3026 
3027  return result;
3028 }
bool query_contains_extern_params(Query *query)
Definition: parse_param.c:330
bool isQueryUsingTempRelation(Query *query)
@ OBJECT_MATVIEW
Definition: parsenodes.h:2105

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

2815 {
2816  Query *result;
2817  Query *query;
2818 
2819  if ((stmt->options & CURSOR_OPT_SCROLL) &&
2820  (stmt->options & CURSOR_OPT_NO_SCROLL))
2821  ereport(ERROR,
2822  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2823  /* translator: %s is a SQL keyword */
2824  errmsg("cannot specify both %s and %s",
2825  "SCROLL", "NO SCROLL")));
2826 
2827  if ((stmt->options & CURSOR_OPT_ASENSITIVE) &&
2828  (stmt->options & CURSOR_OPT_INSENSITIVE))
2829  ereport(ERROR,
2830  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2831  /* translator: %s is a SQL keyword */
2832  errmsg("cannot specify both %s and %s",
2833  "ASENSITIVE", "INSENSITIVE")));
2834 
2835  /* Transform contained query, not allowing SELECT INTO */
2836  query = transformStmt(pstate, stmt->query);
2837  stmt->query = (Node *) query;
2838 
2839  /* Grammar should not have allowed anything but SELECT */
2840  if (!IsA(query, Query) ||
2841  query->commandType != CMD_SELECT)
2842  elog(ERROR, "unexpected non-SELECT command in DECLARE CURSOR");
2843 
2844  /*
2845  * We also disallow data-modifying WITH in a cursor. (This could be
2846  * allowed, but the semantics of when the updates occur might be
2847  * surprising.)
2848  */
2849  if (query->hasModifyingCTE)
2850  ereport(ERROR,
2851  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2852  errmsg("DECLARE CURSOR must not contain data-modifying statements in WITH")));
2853 
2854  /* FOR UPDATE and WITH HOLD are not compatible */
2855  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_HOLD))
2856  ereport(ERROR,
2857  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2858  /*------
2859  translator: %s is a SQL row locking clause such as FOR UPDATE */
2860  errmsg("DECLARE CURSOR WITH HOLD ... %s is not supported",
2862  linitial(query->rowMarks))->strength)),
2863  errdetail("Holdable cursors must be READ ONLY.")));
2864 
2865  /* FOR UPDATE and SCROLL are not compatible */
2866  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL))
2867  ereport(ERROR,
2868  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2869  /*------
2870  translator: %s is a SQL row locking clause such as FOR UPDATE */
2871  errmsg("DECLARE SCROLL CURSOR ... %s is not supported",
2873  linitial(query->rowMarks))->strength)),
2874  errdetail("Scrollable cursors must be READ ONLY.")));
2875 
2876  /* FOR UPDATE and INSENSITIVE are not compatible */
2877  if (query->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE))
2878  ereport(ERROR,
2879  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
2880  /*------
2881  translator: %s is a SQL row locking clause such as FOR UPDATE */
2882  errmsg("DECLARE INSENSITIVE CURSOR ... %s is not valid",
2884  linitial(query->rowMarks))->strength)),
2885  errdetail("Insensitive cursors must be READ ONLY.")));
2886 
2887  /* represent the command as a utility Query */
2888  result = makeNode(Query);
2889  result->commandType = CMD_UTILITY;
2890  result->utilityStmt = (Node *) stmt;
2891 
2892  return result;
2893 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
@ CMD_SELECT
Definition: nodes.h:276
#define CURSOR_OPT_INSENSITIVE
Definition: parsenodes.h:3117
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:3115
#define CURSOR_OPT_HOLD
Definition: parsenodes.h:3119
#define CURSOR_OPT_ASENSITIVE
Definition: parsenodes.h:3118
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:3116
#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 473 of file analyze.c.

474 {
475  Query *qry = makeNode(Query);
476  ParseNamespaceItem *nsitem;
477  Node *qual;
478 
479  qry->commandType = CMD_DELETE;
480 
481  /* process the WITH clause independently of all else */
482  if (stmt->withClause)
483  {
484  qry->hasRecursive = stmt->withClause->recursive;
485  qry->cteList = transformWithClause(pstate, stmt->withClause);
486  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
487  }
488 
489  /* set up range table with just the result rel */
490  qry->resultRelation = setTargetTable(pstate, stmt->relation,
491  stmt->relation->inh,
492  true,
493  ACL_DELETE);
494  nsitem = pstate->p_target_nsitem;
495 
496  /* there's no DISTINCT in DELETE */
497  qry->distinctClause = NIL;
498 
499  /* subqueries in USING cannot access the result relation */
500  nsitem->p_lateral_only = true;
501  nsitem->p_lateral_ok = false;
502 
503  /*
504  * The USING clause is non-standard SQL syntax, and is equivalent in
505  * functionality to the FROM list that can be specified for UPDATE. The
506  * USING keyword is used rather than FROM because FROM is already a
507  * keyword in the DELETE syntax.
508  */
509  transformFromClause(pstate, stmt->usingClause);
510 
511  /* remaining clauses can reference the result relation normally */
512  nsitem->p_lateral_only = false;
513  nsitem->p_lateral_ok = true;
514 
515  qual = transformWhereClause(pstate, stmt->whereClause,
516  EXPR_KIND_WHERE, "WHERE");
517 
518  qry->returningList = transformReturningList(pstate, stmt->returningList);
519 
520  /* done building the range table and jointree */
521  qry->rtable = pstate->p_rtable;
522  qry->rteperminfos = pstate->p_rteperminfos;
523  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
524 
525  qry->hasSubLinks = pstate->p_hasSubLinks;
526  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
527  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
528  qry->hasAggs = pstate->p_hasAggs;
529 
530  assign_query_collations(pstate, qry);
531 
532  /* this must be done after collations, for reliable comparison of exprs */
533  if (pstate->p_hasAggs)
534  parseCheckAggregates(pstate, qry);
535 
536  return qry;
537 }
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:288
@ CMD_DELETE
Definition: nodes.h:279
void parseCheckAggregates(ParseState *pstate, Query *qry)
Definition: parse_agg.c:1066
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
void transformFromClause(ParseState *pstate, List *frmList)
Definition: parse_clause.c:116
int setTargetTable(ParseState *pstate, RangeVar *relation, bool inh, bool alsoSource, AclMode requiredPerms)
Definition: parse_clause.c:182
void assign_query_collations(ParseState *pstate, Query *query)
List * transformWithClause(ParseState *pstate, WithClause *withClause)
Definition: parse_cte.c:109
@ EXPR_KIND_WHERE
Definition: parse_node.h:46
#define ACL_DELETE
Definition: parsenodes.h:86
static List * transformReturningList(ParseState *pstate, List *returningList)
Definition: analyze.c:2507
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:182
List * returningList
Definition: parsenodes.h:196
List * cteList
Definition: parsenodes.h:173
List * rtable
Definition: parsenodes.h:175

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

2908 {
2909  Query *result;
2910  bool generic_plan = false;
2911  Oid *paramTypes = NULL;
2912  int numParams = 0;
2913 
2914  /*
2915  * If we have no external source of parameter definitions, and the
2916  * GENERIC_PLAN option is specified, then accept variable parameter
2917  * definitions (similarly to PREPARE, for example).
2918  */
2919  if (pstate->p_paramref_hook == NULL)
2920  {
2921  ListCell *lc;
2922 
2923  foreach(lc, stmt->options)
2924  {
2925  DefElem *opt = (DefElem *) lfirst(lc);
2926 
2927  if (strcmp(opt->defname, "generic_plan") == 0)
2928  generic_plan = defGetBoolean(opt);
2929  /* don't "break", as we want the last value */
2930  }
2931  if (generic_plan)
2932  setup_parse_variable_parameters(pstate, &paramTypes, &numParams);
2933  }
2934 
2935  /* transform contained query, allowing SELECT INTO */
2936  stmt->query = (Node *) transformOptionalSelectInto(pstate, stmt->query);
2937 
2938  /* make sure all is well with parameter types */
2939  if (generic_plan)
2940  check_variable_parameters(pstate, (Query *) stmt->query);
2941 
2942  /* represent the command as a utility Query */
2943  result = makeNode(Query);
2944  result->commandType = CMD_UTILITY;
2945  result->utilityStmt = (Node *) stmt;
2946 
2947  return result;
2948 }
bool defGetBoolean(DefElem *def)
Definition: define.c:108
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:275
char * defname
Definition: parsenodes.h:810
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 971 of file analyze.c.

974 {
975  List *result;
976  ListCell *lc;
977  ListCell *icols;
978  ListCell *attnos;
979 
980  /*
981  * Check length of expr list. It must not have more expressions than
982  * there are target columns. We allow fewer, but only if no explicit
983  * columns list was given (the remaining columns are implicitly
984  * defaulted). Note we must check this *after* transformation because
985  * that could expand '*' into multiple items.
986  */
987  if (list_length(exprlist) > list_length(icolumns))
988  ereport(ERROR,
989  (errcode(ERRCODE_SYNTAX_ERROR),
990  errmsg("INSERT has more expressions than target columns"),
991  parser_errposition(pstate,
992  exprLocation(list_nth(exprlist,
993  list_length(icolumns))))));
994  if (stmtcols != NIL &&
995  list_length(exprlist) < list_length(icolumns))
996  {
997  /*
998  * We can get here for cases like INSERT ... SELECT (a,b,c) FROM ...
999  * where the user accidentally created a RowExpr instead of separate
1000  * columns. Add a suitable hint if that seems to be the problem,
1001  * because the main error message is quite misleading for this case.
1002  * (If there's no stmtcols, you'll get something about data type
1003  * mismatch, which is less misleading so we don't worry about giving a
1004  * hint in that case.)
1005  */
1006  ereport(ERROR,
1007  (errcode(ERRCODE_SYNTAX_ERROR),
1008  errmsg("INSERT has more target columns than expressions"),
1009  ((list_length(exprlist) == 1 &&
1010  count_rowexpr_columns(pstate, linitial(exprlist)) ==
1011  list_length(icolumns)) ?
1012  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),
1013  parser_errposition(pstate,
1014  exprLocation(list_nth(icolumns,
1015  list_length(exprlist))))));
1016  }
1017 
1018  /*
1019  * Prepare columns for assignment to target table.
1020  */
1021  result = NIL;
1022  forthree(lc, exprlist, icols, icolumns, attnos, attrnos)
1023  {
1024  Expr *expr = (Expr *) lfirst(lc);
1025  ResTarget *col = lfirst_node(ResTarget, icols);
1026  int attno = lfirst_int(attnos);
1027 
1028  expr = transformAssignedExpr(pstate, expr,
1030  col->name,
1031  attno,
1032  col->indirection,
1033  col->location);
1034 
1035  if (strip_indirection)
1036  {
1037  while (expr)
1038  {
1039  if (IsA(expr, FieldStore))
1040  {
1041  FieldStore *fstore = (FieldStore *) expr;
1042 
1043  expr = (Expr *) linitial(fstore->newvals);
1044  }
1045  else if (IsA(expr, SubscriptingRef))
1046  {
1047  SubscriptingRef *sbsref = (SubscriptingRef *) expr;
1048 
1049  if (sbsref->refassgnexpr == NULL)
1050  break;
1051 
1052  expr = sbsref->refassgnexpr;
1053  }
1054  else
1055  break;
1056  }
1057  }
1058 
1059  result = lappend(result, expr);
1060  }
1061 
1062  return result;
1063 }
int errhint(const char *fmt,...)
Definition: elog.c:1316
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1296
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:1247
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define lfirst_int(lc)
Definition: pg_list.h:173
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:512
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
List * newvals
Definition: primnodes.h:1087
int location
Definition: parsenodes.h:518
List * indirection
Definition: parsenodes.h:516
char * name
Definition: parsenodes.h:515
Expr * refassgnexpr
Definition: primnodes.h:630

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

Referenced by transformInsertStmt(), and transformMergeStmt().

◆ transformInsertStmt()

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

Definition at line 544 of file analyze.c.

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

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

Referenced by transformStmt().

◆ transformLockingClause()

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

Definition at line 3248 of file analyze.c.

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

References ACL_SELECT_FOR_UPDATE, RangeTblEntry::alias, Alias::aliasname, applyLockingClause(), RangeVar::catalogname, CheckSelectLocking(), elog(), RangeTblEntry::eref, ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, getRTEPermissionInfo(), i, RangeTblEntry::inFromCl, RangeTblEntry::join_using_alias, LCS_asString(), lfirst, RangeVar::location, LockingClause::lockedRels, makeNode, NIL, parser_errposition(), RangeVar::relname, RTEPermissionInfo::requiredPerms, Query::rtable, RTE_CTE, RTE_FUNCTION, RTE_JOIN, RTE_NAMEDTUPLESTORE, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, RangeVar::schemaname, LockingClause::strength, RangeTblEntry::subquery, and LockingClause::waitPolicy.

Referenced by transformPLAssignStmt(), transformSelectStmt(), and transformSetOperationStmt().

◆ transformOnConflictClause()

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

Definition at line 1070 of file analyze.c.

1072 {
1073  ParseNamespaceItem *exclNSItem = NULL;
1074  List *arbiterElems;
1075  Node *arbiterWhere;
1076  Oid arbiterConstraint;
1077  List *onConflictSet = NIL;
1078  Node *onConflictWhere = NULL;
1079  int exclRelIndex = 0;
1080  List *exclRelTlist = NIL;
1081  OnConflictExpr *result;
1082 
1083  /*
1084  * If this is ON CONFLICT ... UPDATE, first create the range table entry
1085  * for the EXCLUDED pseudo relation, so that that will be present while
1086  * processing arbiter expressions. (You can't actually reference it from
1087  * there, but this provides a useful error message if you try.)
1088  */
1089  if (onConflictClause->action == ONCONFLICT_UPDATE)
1090  {
1091  Relation targetrel = pstate->p_target_relation;
1092  RangeTblEntry *exclRte;
1093 
1094  exclNSItem = addRangeTableEntryForRelation(pstate,
1095  targetrel,
1097  makeAlias("excluded", NIL),
1098  false, false);
1099  exclRte = exclNSItem->p_rte;
1100  exclRelIndex = exclNSItem->p_rtindex;
1101 
1102  /*
1103  * relkind is set to composite to signal that we're not dealing with
1104  * an actual relation, and no permission checks are required on it.
1105  * (We'll check the actual target relation, instead.)
1106  */
1107  exclRte->relkind = RELKIND_COMPOSITE_TYPE;
1108 
1109  /* Create EXCLUDED rel's targetlist for use by EXPLAIN */
1110  exclRelTlist = BuildOnConflictExcludedTargetlist(targetrel,
1111  exclRelIndex);
1112  }
1113 
1114  /* Process the arbiter clause, ON CONFLICT ON (...) */
1115  transformOnConflictArbiter(pstate, onConflictClause, &arbiterElems,
1116  &arbiterWhere, &arbiterConstraint);
1117 
1118  /* Process DO UPDATE */
1119  if (onConflictClause->action == ONCONFLICT_UPDATE)
1120  {
1121  /*
1122  * Expressions in the UPDATE targetlist need to be handled like UPDATE
1123  * not INSERT. We don't need to save/restore this because all INSERT
1124  * expressions have been parsed already.
1125  */
1126  pstate->p_is_insert = false;
1127 
1128  /*
1129  * Add the EXCLUDED pseudo relation to the query namespace, making it
1130  * available in the UPDATE subexpressions.
1131  */
1132  addNSItemToQuery(pstate, exclNSItem, false, true, true);
1133 
1134  /*
1135  * Now transform the UPDATE subexpressions.
1136  */
1137  onConflictSet =
1138  transformUpdateTargetList(pstate, onConflictClause->targetList);
1139 
1140  onConflictWhere = transformWhereClause(pstate,
1141  onConflictClause->whereClause,
1142  EXPR_KIND_WHERE, "WHERE");
1143 
1144  /*
1145  * Remove the EXCLUDED pseudo relation from the query namespace, since
1146  * it's not supposed to be available in RETURNING. (Maybe someday we
1147  * could allow that, and drop this step.)
1148  */
1149  Assert((ParseNamespaceItem *) llast(pstate->p_namespace) == exclNSItem);
1150  pstate->p_namespace = list_delete_last(pstate->p_namespace);
1151  }
1152 
1153  /* Finally, build ON CONFLICT DO [NOTHING | UPDATE] expression */
1154  result = makeNode(OnConflictExpr);
1155 
1156  result->action = onConflictClause->action;
1157  result->arbiterElems = arbiterElems;
1158  result->arbiterWhere = arbiterWhere;
1159  result->constraint = arbiterConstraint;
1160  result->onConflictSet = onConflictSet;
1161  result->onConflictWhere = onConflictWhere;
1162  result->exclRelIndex = exclRelIndex;
1163  result->exclRelTlist = exclRelTlist;
1164 
1165  return result;
1166 }
List * list_delete_last(List *list)
Definition: list.c:956
#define RowExclusiveLock
Definition: lockdefs.h:38
void transformOnConflictArbiter(ParseState *pstate, OnConflictClause *onConflictClause, List **arbiterExpr, Node **arbiterWhere, Oid *constraint)
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
List * transformUpdateTargetList(ParseState *pstate, List *origTlist)
Definition: analyze.c:2435
List * BuildOnConflictExcludedTargetlist(Relation targetrel, Index exclRelIndex)
Definition: analyze.c:1177
#define llast(l)
Definition: pg_list.h:198
OnConflictAction action
Definition: parsenodes.h:1578
List * arbiterElems
Definition: primnodes.h:1979
OnConflictAction action
Definition: primnodes.h:1976
List * onConflictSet
Definition: primnodes.h:1985
List * exclRelTlist
Definition: primnodes.h:1988
Node * onConflictWhere
Definition: primnodes.h:1986
Node * arbiterWhere
Definition: primnodes.h:1981
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:1934
@ OBJECT_TABLE
Definition: parsenodes.h:2123
IntoClause * into
Definition: parsenodes.h:3720
ObjectType objtype
Definition: parsenodes.h:3721

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

2566 {
2567  Query *qry = makeNode(Query);
2568  ColumnRef *cref = makeNode(ColumnRef);
2569  List *indirection = stmt->indirection;
2570  int nnames = stmt->nnames;
2571  SelectStmt *sstmt = stmt->val;
2572  Node *target;
2573  Oid targettype;
2574  int32 targettypmod;
2575  Oid targetcollation;
2576  List *tlist;
2577  TargetEntry *tle;
2578  Oid type_id;
2579  Node *qual;
2580  ListCell *l;
2581 
2582  /*
2583  * First, construct a ColumnRef for the target variable. If the target
2584  * has more than one dotted name, we have to pull the extra names out of
2585  * the indirection list.
2586  */
2587  cref->fields = list_make1(makeString(stmt->name));
2588  cref->location = stmt->location;
2589  if (nnames > 1)
2590  {
2591  /* avoid munging the raw parsetree */
2592  indirection = list_copy(indirection);
2593  while (--nnames > 0 && indirection != NIL)
2594  {
2595  Node *ind = (Node *) linitial(indirection);
2596 
2597  if (!IsA(ind, String))
2598  elog(ERROR, "invalid name count in PLAssignStmt");
2599  cref->fields = lappend(cref->fields, ind);
2600  indirection = list_delete_first(indirection);
2601  }
2602  }
2603 
2604  /*
2605  * Transform the target reference. Typically we will get back a Param
2606  * node, but there's no reason to be too picky about its type.
2607  */
2608  target = transformExpr(pstate, (Node *) cref,
2610  targettype = exprType(target);
2611  targettypmod = exprTypmod(target);
2612  targetcollation = exprCollation(target);
2613 
2614  /*
2615  * The rest mostly matches transformSelectStmt, except that we needn't
2616  * consider WITH or INTO, and we build a targetlist our own way.
2617  */
2618  qry->commandType = CMD_SELECT;
2619  pstate->p_is_insert = false;
2620 
2621  /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
2622  pstate->p_locking_clause = sstmt->lockingClause;
2623 
2624  /* make WINDOW info available for window functions, too */
2625  pstate->p_windowdefs = sstmt->windowClause;
2626 
2627  /* process the FROM clause */
2628  transformFromClause(pstate, sstmt->fromClause);
2629 
2630  /* initially transform the targetlist as if in SELECT */
2631  tlist = transformTargetList(pstate, sstmt->targetList,
2633 
2634  /* we should have exactly one targetlist item */
2635  if (list_length(tlist) != 1)
2636  ereport(ERROR,
2637  (errcode(ERRCODE_SYNTAX_ERROR),
2638  errmsg_plural("assignment source returned %d column",
2639  "assignment source returned %d columns",
2640  list_length(tlist),
2641  list_length(tlist))));
2642 
2643  tle = linitial_node(TargetEntry, tlist);
2644 
2645  /*
2646  * This next bit is similar to transformAssignedExpr; the key difference
2647  * is we use COERCION_PLPGSQL not COERCION_ASSIGNMENT.
2648  */
2649  type_id = exprType((Node *) tle->expr);
2650 
2652 
2653  if (indirection)
2654  {
2655  tle->expr = (Expr *)
2657  target,
2658  stmt->name,
2659  false,
2660  targettype,
2661  targettypmod,
2662  targetcollation,
2663  indirection,
2664  list_head(indirection),
2665  (Node *) tle->expr,
2667  exprLocation(target));
2668  }
2669  else if (targettype != type_id &&
2670  (targettype == RECORDOID || ISCOMPLEX(targettype)) &&
2671  (type_id == RECORDOID || ISCOMPLEX(type_id)))
2672  {
2673  /*
2674  * Hack: do not let coerce_to_target_type() deal with inconsistent
2675  * composite types. Just pass the expression result through as-is,
2676  * and let the PL/pgSQL executor do the conversion its way. This is
2677  * rather bogus, but it's needed for backwards compatibility.
2678  */
2679  }
2680  else
2681  {
2682  /*
2683  * For normal non-qualified target column, do type checking and
2684  * coercion.
2685  */
2686  Node *orig_expr = (Node *) tle->expr;
2687 
2688  tle->expr = (Expr *)
2689  coerce_to_target_type(pstate,
2690  orig_expr, type_id,
2691  targettype, targettypmod,
2694  -1);
2695  /* With COERCION_PLPGSQL, this error is probably unreachable */
2696  if (tle->expr == NULL)
2697  ereport(ERROR,
2698  (errcode(ERRCODE_DATATYPE_MISMATCH),
2699  errmsg("variable \"%s\" is of type %s"
2700  " but expression is of type %s",
2701  stmt->name,
2702  format_type_be(targettype),
2703  format_type_be(type_id)),
2704  errhint("You will need to rewrite or cast the expression."),
2705  parser_errposition(pstate, exprLocation(orig_expr))));
2706  }
2707 
2708  pstate->p_expr_kind = EXPR_KIND_NONE;
2709 
2710  qry->targetList = list_make1(tle);
2711 
2712  /* transform WHERE */
2713  qual = transformWhereClause(pstate, sstmt->whereClause,
2714  EXPR_KIND_WHERE, "WHERE");
2715 
2716  /* initial processing of HAVING clause is much like WHERE clause */
2717  qry->havingQual = transformWhereClause(pstate, sstmt->havingClause,
2718  EXPR_KIND_HAVING, "HAVING");
2719 
2720  /*
2721  * Transform sorting/grouping stuff. Do ORDER BY first because both
2722  * transformGroupClause and transformDistinctClause need the results. Note
2723  * that these functions can also change the targetList, so it's passed to
2724  * them by reference.
2725  */
2726  qry->sortClause = transformSortClause(pstate,
2727  sstmt->sortClause,
2728  &qry->targetList,
2730  false /* allow SQL92 rules */ );
2731 
2732  qry->groupClause = transformGroupClause(pstate,
2733  sstmt->groupClause,
2734  &qry->groupingSets,
2735  &qry->targetList,
2736  qry->sortClause,
2738  false /* allow SQL92 rules */ );
2739 
2740  if (sstmt->distinctClause == NIL)
2741  {
2742  qry->distinctClause = NIL;
2743  qry->hasDistinctOn = false;
2744  }
2745  else if (linitial(sstmt->distinctClause) == NULL)
2746  {
2747  /* We had SELECT DISTINCT */
2749  &qry->targetList,
2750  qry->sortClause,
2751  false);
2752  qry->hasDistinctOn = false;
2753  }
2754  else
2755  {
2756  /* We had SELECT DISTINCT ON */
2758  sstmt->distinctClause,
2759  &qry->targetList,
2760  qry->sortClause);
2761  qry->hasDistinctOn = true;
2762  }
2763 
2764  /* transform LIMIT */
2765  qry->limitOffset = transformLimitClause(pstate, sstmt->limitOffset,
2766  EXPR_KIND_OFFSET, "OFFSET",
2767  sstmt->limitOption);
2768  qry->limitCount = transformLimitClause(pstate, sstmt->limitCount,
2769  EXPR_KIND_LIMIT, "LIMIT",
2770  sstmt->limitOption);
2771  qry->limitOption = sstmt->limitOption;
2772 
2773  /* transform window clauses after we have seen all window functions */
2775  pstate->p_windowdefs,
2776  &qry->targetList);
2777 
2778  qry->rtable = pstate->p_rtable;
2779  qry->rteperminfos = pstate->p_rteperminfos;
2780  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2781 
2782  qry->hasSubLinks = pstate->p_hasSubLinks;
2783  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
2784  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2785  qry->hasAggs = pstate->p_hasAggs;
2786 
2787  foreach(l, sstmt->lockingClause)
2788  {
2789  transformLockingClause(pstate, qry,
2790  (LockingClause *) lfirst(l), false);
2791  }
2792 
2793  assign_query_collations(pstate, qry);
2794 
2795  /* this must be done after collations, for reliable comparison of exprs */
2796  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
2797  parseCheckAggregates(pstate, qry);
2798 
2799  return qry;
2800 }
signed int int32
Definition: c.h:478
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1179
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
List * list_copy(const List *oldlist)
Definition: list.c:1572
List * list_delete_first(List *list)
Definition: list.c:942
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:783
List * transformWindowDefinitions(ParseState *pstate, List *windowdefs, List **targetlist)
List * transformDistinctOnClause(ParseState *pstate, List *distinctlist, List **targetlist, List *sortClause)
Node * transformLimitClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName, LimitOption limitOption)
List * transformSortClause(ParseState *pstate, List *orderlist, List **targetlist, ParseExprKind exprKind, bool useSQL99)
List * transformGroupClause(ParseState *pstate, List *grouplist, List **groupingSets, List **targetlist, List *sortClause, ParseExprKind exprKind, bool useSQL99)
List * transformDistinctClause(ParseState *pstate, List **targetlist, List *sortClause, bool is_agg)
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:78
@ EXPR_KIND_ORDER_BY
Definition: parse_node.h:60
@ EXPR_KIND_OFFSET
Definition: parse_node.h:63
@ EXPR_KIND_HAVING
Definition: parse_node.h:47
@ EXPR_KIND_LIMIT
Definition: parse_node.h:62
@ EXPR_KIND_UPDATE_TARGET
Definition: parse_node.h:57
@ EXPR_KIND_SELECT_TARGET
Definition: parse_node.h:54
@ EXPR_KIND_NONE
Definition: parse_node.h:40
@ EXPR_KIND_GROUP_BY
Definition: parse_node.h:59
List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind)
Definition: parse_target.c:122
Node * transformAssignmentIndirection(ParseState *pstate, Node *basenode, const char *targetName, bool targetIsSubscripting, Oid targetTypeId, int32 targetTypMod, Oid targetCollation, List *indirection, ListCell *indirection_cell, Node *rhs, CoercionContext ccontext, int location)
Definition: parse_target.c:684
#define ISCOMPLEX(typeid)
Definition: parse_type.h:59
#define linitial_node(type, l)
Definition: pg_list.h:181
#define list_make1(x1)
Definition: pg_list.h:212
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:663
@ COERCION_PLPGSQL
Definition: primnodes.h:643
int location
Definition: parsenodes.h:293
List * fields
Definition: parsenodes.h:292
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:212
Node * limitOffset
Definition: parsenodes.h:211
LimitOption limitOption
Definition: parsenodes.h:213
List * windowClause
Definition: parsenodes.h:205
List * sortClause
Definition: parsenodes.h:209
LimitOption limitOption
Definition: parsenodes.h:1975
List * targetList
Definition: parsenodes.h:1950
List * fromClause
Definition: parsenodes.h:1951
List * groupClause
Definition: parsenodes.h:1953
Node * havingClause
Definition: parsenodes.h:1955
List * windowClause
Definition: parsenodes.h:1956
List * distinctClause
Definition: parsenodes.h:1947
Node * whereClause
Definition: parsenodes.h:1952
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 2507 of file analyze.c.

2508 {
2509  List *rlist;
2510  int save_next_resno;
2511 
2512  if (returningList == NIL)
2513  return NIL; /* nothing to do */
2514 
2515  /*
2516  * We need to assign resnos starting at one in the RETURNING list. Save
2517  * and restore the main tlist's value of p_next_resno, just in case
2518  * someone looks at it later (probably won't happen).
2519  */
2520  save_next_resno = pstate->p_next_resno;
2521  pstate->p_next_resno = 1;
2522 
2523  /* transform RETURNING identically to a SELECT targetlist */
2524  rlist = transformTargetList(pstate, returningList, EXPR_KIND_RETURNING);
2525 
2526  /*
2527  * Complain if the nonempty tlist expanded to nothing (which is possible
2528  * if it contains only a star-expansion of a zero-column table). If we
2529  * allow this, the parsed Query will look like it didn't have RETURNING,
2530  * with results that would probably surprise the user.
2531  */
2532  if (rlist == NIL)
2533  ereport(ERROR,
2534  (errcode(ERRCODE_SYNTAX_ERROR),
2535  errmsg("RETURNING must have at least one column"),
2536  parser_errposition(pstate,
2537  exprLocation(linitial(returningList)))));
2538 
2539  /* mark column origins */
2540  markTargetListOrigins(pstate, rlist);
2541 
2542  /* resolve any still-unresolved output columns as being type text */
2543  if (pstate->p_resolve_unknowns)
2544  resolveTargetListUnknowns(pstate, rlist);
2545 
2546  /* restore state */
2547  pstate->p_next_resno = save_next_resno;
2548 
2549  return rlist;
2550 }
@ 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 2339 of file analyze.c.

2340 {
2341  Query *qry = makeNode(Query);
2342 
2343  qry->commandType = CMD_SELECT;
2344  qry->isReturn = true;
2345 
2347  1, NULL, false));
2348 
2349  if (pstate->p_resolve_unknowns)
2350  resolveTargetListUnknowns(pstate, qry->targetList);
2351  qry->rtable = pstate->p_rtable;
2352  qry->rteperminfos = pstate->p_rteperminfos;
2353  qry->jointree = makeFromExpr(pstate->p_joinlist, NULL);
2354  qry->hasSubLinks = pstate->p_hasSubLinks;
2355  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
2356  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2357  qry->hasAggs = pstate->p_hasAggs;
2358 
2359  assign_query_collations(pstate, qry);
2360 
2361  return qry;
2362 }

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

1290 {
1291  Query *qry = makeNode(Query);
1292  Node *qual;
1293  ListCell *l;
1294 
1295  qry->commandType = CMD_SELECT;
1296 
1297  /* process the WITH clause independently of all else */
1298  if (stmt->withClause)
1299  {
1300  qry->hasRecursive = stmt->withClause->recursive;
1301  qry->cteList = transformWithClause(pstate, stmt->withClause);
1302  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
1303  }
1304 
1305  /* Complain if we get called from someplace where INTO is not allowed */
1306  if (stmt->intoClause)
1307  ereport(ERROR,
1308  (errcode(ERRCODE_SYNTAX_ERROR),
1309  errmsg("SELECT ... INTO is not allowed here"),
1310  parser_errposition(pstate,
1311  exprLocation((Node *) stmt->intoClause))));
1312 
1313  /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */
1314  pstate->p_locking_clause = stmt->lockingClause;
1315 
1316  /* make WINDOW info available for window functions, too */
1317  pstate->p_windowdefs = stmt->windowClause;
1318 
1319  /* process the FROM clause */
1320  transformFromClause(pstate, stmt->fromClause);
1321 
1322  /* transform targetlist */
1323  qry->targetList = transformTargetList(pstate, stmt->targetList,
1325 
1326  /* mark column origins */
1327  markTargetListOrigins(pstate, qry->targetList);
1328 
1329  /* transform WHERE */
1330  qual = transformWhereClause(pstate, stmt->whereClause,
1331  EXPR_KIND_WHERE, "WHERE");
1332 
1333  /* initial processing of HAVING clause is much like WHERE clause */
1334  qry->havingQual = transformWhereClause(pstate, stmt->havingClause,
1335  EXPR_KIND_HAVING, "HAVING");
1336 
1337  /*
1338  * Transform sorting/grouping stuff. Do ORDER BY first because both
1339  * transformGroupClause and transformDistinctClause need the results. Note
1340  * that these functions can also change the targetList, so it's passed to
1341  * them by reference.
1342  */
1343  qry->sortClause = transformSortClause(pstate,
1344  stmt->sortClause,
1345  &qry->targetList,
1347  false /* allow SQL92 rules */ );
1348 
1349  qry->groupClause = transformGroupClause(pstate,
1350  stmt->groupClause,
1351  &qry->groupingSets,
1352  &qry->targetList,
1353  qry->sortClause,
1355  false /* allow SQL92 rules */ );
1356  qry->groupDistinct = stmt->groupDistinct;
1357 
1358  if (stmt->distinctClause == NIL)
1359  {
1360  qry->distinctClause = NIL;
1361  qry->hasDistinctOn = false;
1362  }
1363  else if (linitial(stmt->distinctClause) == NULL)
1364  {
1365  /* We had SELECT DISTINCT */
1367  &qry->targetList,
1368  qry->sortClause,
1369  false);
1370  qry->hasDistinctOn = false;
1371  }
1372  else
1373  {
1374  /* We had SELECT DISTINCT ON */
1376  stmt->distinctClause,
1377  &qry->targetList,
1378  qry->sortClause);
1379  qry->hasDistinctOn = true;
1380  }
1381 
1382  /* transform LIMIT */
1383  qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
1384  EXPR_KIND_OFFSET, "OFFSET",
1385  stmt->limitOption);
1386  qry->limitCount = transformLimitClause(pstate, stmt->limitCount,
1387  EXPR_KIND_LIMIT, "LIMIT",
1388  stmt->limitOption);
1389  qry->limitOption = stmt->limitOption;
1390 
1391  /* transform window clauses after we have seen all window functions */
1393  pstate->p_windowdefs,
1394  &qry->targetList);
1395 
1396  /* resolve any still-unresolved output columns as being type text */
1397  if (pstate->p_resolve_unknowns)
1398  resolveTargetListUnknowns(pstate, qry->targetList);
1399 
1400  qry->rtable = pstate->p_rtable;
1401  qry->rteperminfos = pstate->p_rteperminfos;
1402  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
1403 
1404  qry->hasSubLinks = pstate->p_hasSubLinks;
1405  qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
1406  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
1407  qry->hasAggs = pstate->p_hasAggs;
1408 
1409  foreach(l, stmt->lockingClause)
1410  {
1411  transformLockingClause(pstate, qry,
1412  (LockingClause *) lfirst(l), false);
1413  }
1414 
1415  assign_query_collations(pstate, qry);
1416 
1417  /* this must be done after collations, for reliable comparison of exprs */
1418  if (pstate->p_hasAggs || qry->groupClause || qry->groupingSets || qry->havingQual)
1419  parseCheckAggregates(pstate, qry);
1420 
1421  return qry;
1422 }
bool groupDistinct
Definition: parsenodes.h:199

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

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

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

1956 {
1957  bool isLeaf;
1958 
1959  Assert(stmt && IsA(stmt, SelectStmt));
1960 
1961  /* Guard against stack overflow due to overly complex set-expressions */
1963 
1964  /*
1965  * Validity-check both leaf and internal SELECTs for disallowed ops.
1966  */
1967  if (stmt->intoClause)
1968  ereport(ERROR,
1969  (errcode(ERRCODE_SYNTAX_ERROR),
1970  errmsg("INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"),
1971  parser_errposition(pstate,
1972  exprLocation((Node *) stmt->intoClause))));
1973 
1974  /* We don't support FOR UPDATE/SHARE with set ops at the moment. */
1975  if (stmt->lockingClause)
1976  ereport(ERROR,
1977  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1978  /*------
1979  translator: %s is a SQL row locking clause such as FOR UPDATE */
1980  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
1982  linitial(stmt->lockingClause))->strength))));
1983 
1984  /*
1985  * If an internal node of a set-op tree has ORDER BY, LIMIT, FOR UPDATE,
1986  * or WITH clauses attached, we need to treat it like a leaf node to
1987  * generate an independent sub-Query tree. Otherwise, it can be
1988  * represented by a SetOperationStmt node underneath the parent Query.
1989  */
1990  if (stmt->op == SETOP_NONE)
1991  {
1992  Assert(stmt->larg == NULL && stmt->rarg == NULL);
1993  isLeaf = true;
1994  }
1995  else
1996  {
1997  Assert(stmt->larg != NULL && stmt->rarg != NULL);
1998  if (stmt->sortClause || stmt->limitOffset || stmt->limitCount ||
1999  stmt->lockingClause || stmt->withClause)
2000  isLeaf = true;
2001  else
2002  isLeaf = false;
2003  }
2004 
2005  if (isLeaf)
2006  {
2007  /* Process leaf SELECT */
2008  Query *selectQuery;
2009  char selectName[32];
2010  ParseNamespaceItem *nsitem;
2011  RangeTblRef *rtr;
2012  ListCell *tl;
2013 
2014  /*
2015  * Transform SelectStmt into a Query.
2016  *
2017  * This works the same as SELECT transformation normally would, except
2018  * that we prevent resolving unknown-type outputs as TEXT. This does
2019  * not change the subquery's semantics since if the column type
2020  * matters semantically, it would have been resolved to something else
2021  * anyway. Doing this lets us resolve such outputs using
2022  * select_common_type(), below.
2023  *
2024  * Note: previously transformed sub-queries don't affect the parsing
2025  * of this sub-query, because they are not in the toplevel pstate's
2026  * namespace list.
2027  */
2028  selectQuery = parse_sub_analyze((Node *) stmt, pstate,
2029  NULL, false, false);
2030 
2031  /*
2032  * Check for bogus references to Vars on the current query level (but
2033  * upper-level references are okay). Normally this can't happen
2034  * because the namespace will be empty, but it could happen if we are
2035  * inside a rule.
2036  */
2037  if (pstate->p_namespace)
2038  {
2039  if (contain_vars_of_level((Node *) selectQuery, 1))
2040  ereport(ERROR,
2041  (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
2042  errmsg("UNION/INTERSECT/EXCEPT member statement cannot refer to other relations of same query level"),
2043  parser_errposition(pstate,
2044  locate_var_of_level((Node *) selectQuery, 1))));
2045  }
2046 
2047  /*
2048  * Extract a list of the non-junk TLEs for upper-level processing.
2049  */
2050  if (targetlist)
2051  {
2052  *targetlist = NIL;
2053  foreach(tl, selectQuery->targetList)
2054  {
2055  TargetEntry *tle = (TargetEntry *) lfirst(tl);
2056 
2057  if (!tle->resjunk)
2058  *targetlist = lappend(*targetlist, tle);
2059  }
2060  }
2061 
2062  /*
2063  * Make the leaf query be a subquery in the top-level rangetable.
2064  */
2065  snprintf(selectName, sizeof(selectName), "*SELECT* %d",
2066  list_length(pstate->p_rtable) + 1);
2067  nsitem = addRangeTableEntryForSubquery(pstate,
2068  selectQuery,
2069  makeAlias(selectName, NIL),
2070  false,
2071  false);
2072 
2073  /*
2074  * Return a RangeTblRef to replace the SelectStmt in the set-op tree.
2075  */
2076  rtr = makeNode(RangeTblRef);
2077  rtr->rtindex = nsitem->p_rtindex;
2078  return (Node *) rtr;
2079  }
2080  else
2081  {
2082  /* Process an internal node (set operation node) */
2084  List *ltargetlist;
2085  List *rtargetlist;
2086  ListCell *ltl;
2087  ListCell *rtl;
2088  const char *context;
2089  bool recursive = (pstate->p_parent_cte &&
2090  pstate->p_parent_cte->cterecursive);
2091 
2092  context = (stmt->op == SETOP_UNION ? "UNION" :
2093  (stmt->op == SETOP_INTERSECT ? "INTERSECT" :
2094  "EXCEPT"));
2095 
2096  op->op = stmt->op;
2097  op->all = stmt->all;
2098 
2099  /*
2100  * Recursively transform the left child node.
2101  */
2102  op->larg = transformSetOperationTree(pstate, stmt->larg,
2103  false,
2104  &ltargetlist);
2105 
2106  /*
2107  * If we are processing a recursive union query, now is the time to
2108  * examine the non-recursive term's output columns and mark the
2109  * containing CTE as having those result columns. We should do this
2110  * only at the topmost setop of the CTE, of course.
2111  */
2112  if (isTopLevel && recursive)
2113  determineRecursiveColTypes(pstate, op->larg, ltargetlist);
2114 
2115  /*
2116  * Recursively transform the right child node.
2117  */
2118  op->rarg = transformSetOperationTree(pstate, stmt->rarg,
2119  false,
2120  &rtargetlist);
2121 
2122  /*
2123  * Verify that the two children have the same number of non-junk
2124  * columns, and determine the types of the merged output columns.
2125  */
2126  if (list_length(ltargetlist) != list_length(rtargetlist))
2127  ereport(ERROR,
2128  (errcode(ERRCODE_SYNTAX_ERROR),
2129  errmsg("each %s query must have the same number of columns",
2130  context),
2131  parser_errposition(pstate,
2132  exprLocation((Node *) rtargetlist))));
2133 
2134  if (targetlist)
2135  *targetlist = NIL;
2136  op->colTypes = NIL;
2137  op->colTypmods = NIL;
2138  op->colCollations = NIL;
2139  op->groupClauses = NIL;
2140  forboth(ltl, ltargetlist, rtl, rtargetlist)
2141  {
2142  TargetEntry *ltle = (TargetEntry *) lfirst(ltl);
2143  TargetEntry *rtle = (TargetEntry *) lfirst(rtl);
2144  Node *lcolnode = (Node *) ltle->expr;
2145  Node *rcolnode = (Node *) rtle->expr;
2146  Oid lcoltype = exprType(lcolnode);
2147  Oid rcoltype = exprType(rcolnode);
2148  Node *bestexpr;
2149  int bestlocation;
2150  Oid rescoltype;
2151  int32 rescoltypmod;
2152  Oid rescolcoll;
2153 
2154  /* select common type, same as CASE et al */
2155  rescoltype = select_common_type(pstate,
2156  list_make2(lcolnode, rcolnode),
2157  context,
2158  &bestexpr);
2159  bestlocation = exprLocation(bestexpr);
2160 
2161  /*
2162  * Verify the coercions are actually possible. If not, we'd fail
2163  * later anyway, but we want to fail now while we have sufficient
2164  * context to produce an error cursor position.
2165  *
2166  * For all non-UNKNOWN-type cases, we verify coercibility but we
2167  * don't modify the child's expression, for fear of changing the
2168  * child query's semantics.
2169  *
2170  * If a child expression is an UNKNOWN-type Const or Param, we
2171  * want to replace it with the coerced expression. This can only
2172  * happen when the child is a leaf set-op node. It's safe to
2173  * replace the expression because if the child query's semantics
2174  * depended on the type of this output column, it'd have already
2175  * coerced the UNKNOWN to something else. We want to do this
2176  * because (a) we want to verify that a Const is valid for the
2177  * target type, or resolve the actual type of an UNKNOWN Param,
2178  * and (b) we want to avoid unnecessary discrepancies between the
2179  * output type of the child query and the resolved target type.
2180  * Such a discrepancy would disable optimization in the planner.
2181  *
2182  * If it's some other UNKNOWN-type node, eg a Var, we do nothing
2183  * (knowing that coerce_to_common_type would fail). The planner
2184  * is sometimes able to fold an UNKNOWN Var to a constant before
2185  * it has to coerce the type, so failing now would just break
2186  * cases that might work.
2187  */
2188  if (lcoltype != UNKNOWNOID)
2189  lcolnode = coerce_to_common_type(pstate, lcolnode,
2190  rescoltype, context);
2191  else if (IsA(lcolnode, Const) ||
2192  IsA(lcolnode, Param))
2193  {
2194  lcolnode = coerce_to_common_type(pstate, lcolnode,
2195  rescoltype, context);
2196  ltle->expr = (Expr *) lcolnode;
2197  }
2198 
2199  if (rcoltype != UNKNOWNOID)
2200  rcolnode = coerce_to_common_type(pstate, rcolnode,
2201  rescoltype, context);
2202  else if (IsA(rcolnode, Const) ||
2203  IsA(rcolnode, Param))
2204  {
2205  rcolnode = coerce_to_common_type(pstate, rcolnode,
2206  rescoltype, context);
2207  rtle->expr = (Expr *) rcolnode;
2208  }
2209 
2210  rescoltypmod = select_common_typmod(pstate,
2211  list_make2(lcolnode, rcolnode),
2212  rescoltype);
2213 
2214  /*
2215  * Select common collation. A common collation is required for
2216  * all set operators except UNION ALL; see SQL:2008 7.13 <query
2217  * expression> Syntax Rule 15c. (If we fail to identify a common
2218  * collation for a UNION ALL column, the colCollations element
2219  * will be set to InvalidOid, which may result in a runtime error
2220  * if something at a higher query level wants to use the column's
2221  * collation.)
2222  */
2223  rescolcoll = select_common_collation(pstate,
2224  list_make2(lcolnode, rcolnode),
2225  (op->op == SETOP_UNION && op->all));
2226 
2227  /* emit results */
2228  op->colTypes = lappend_oid(op->colTypes, rescoltype);
2229  op->colTypmods = lappend_int(op->colTypmods, rescoltypmod);
2230  op->colCollations = lappend_oid(op->colCollations, rescolcoll);
2231 
2232  /*
2233  * For all cases except UNION ALL, identify the grouping operators
2234  * (and, if available, sorting operators) that will be used to
2235  * eliminate duplicates.
2236  */
2237  if (op->op != SETOP_UNION || !op->all)
2238  {
2239  ParseCallbackState pcbstate;
2240 
2241  setup_parser_errposition_callback(&pcbstate, pstate,
2242  bestlocation);
2243 
2244  /*
2245  * If it's a recursive union, we need to require hashing
2246  * support.
2247  */
2248  op->groupClauses = lappend(op->groupClauses,
2249  makeSortGroupClauseForSetOp(rescoltype, recursive));
2250 
2252  }
2253 
2254  /*
2255  * Construct a dummy tlist entry to return. We use a SetToDefault
2256  * node for the expression, since it carries exactly the fields
2257  * needed, but any other expression node type would do as well.
2258  */
2259  if (targetlist)
2260  {
2261  SetToDefault *rescolnode = makeNode(SetToDefault);
2262  TargetEntry *restle;
2263 
2264  rescolnode->typeId = rescoltype;
2265  rescolnode->typeMod = rescoltypmod;
2266  rescolnode->collation = rescolcoll;
2267  rescolnode->location = bestlocation;
2268  restle = makeTargetEntry((Expr *) rescolnode,
2269  0, /* no need to set resno */
2270  NULL,
2271  false);
2272  *targetlist = lappend(*targetlist, restle);
2273  }
2274  }
2275 
2276  return (Node *) op;
2277  }
2278 }
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:1936
@ SETOP_UNION
Definition: parsenodes.h:1935
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:2285
SortGroupClause * makeSortGroupClauseForSetOp(Oid rescoltype, bool require_hash)
Definition: analyze.c:1907
#define list_make2(x1, x2)
Definition: pg_list.h:214
#define snprintf
Definition: port.h:238
void check_stack_depth(void)
Definition: postgres.c:3461
SetOperation op
Definition: parsenodes.h:2012
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  switch (nodeTag(parseTree))
339  {
340  /*
341  * Optimizable statements
342  */
343  case T_InsertStmt:
344  result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
345  break;
346 
347  case T_DeleteStmt:
348  result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
349  break;
350 
351  case T_UpdateStmt:
352  result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
353  break;
354 
355  case T_MergeStmt:
356  result = transformMergeStmt(pstate, (MergeStmt *) parseTree);
357  break;
358 
359  case T_SelectStmt:
360  {
361  SelectStmt *n = (SelectStmt *) parseTree;
362 
363  if (n->valuesLists)
364  result = transformValuesClause(pstate, n);
365  else if (n->op == SETOP_NONE)
366  result = transformSelectStmt(pstate, n);
367  else
368  result = transformSetOperationStmt(pstate, n);
369  }
370  break;
371 
372  case T_ReturnStmt:
373  result = transformReturnStmt(pstate, (ReturnStmt *) parseTree);
374  break;
375 
376  case T_PLAssignStmt:
377  result = transformPLAssignStmt(pstate,
378  (PLAssignStmt *) parseTree);
379  break;
380 
381  /*
382  * Special cases
383  */
384  case T_DeclareCursorStmt:
385  result = transformDeclareCursorStmt(pstate,
386  (DeclareCursorStmt *) parseTree);
387  break;
388 
389  case T_ExplainStmt:
390  result = transformExplainStmt(pstate,
391  (ExplainStmt *) parseTree);
392  break;
393 
394  case T_CreateTableAsStmt:
395  result = transformCreateTableAsStmt(pstate,
396  (CreateTableAsStmt *) parseTree);
397  break;
398 
399  case T_CallStmt:
400  result = transformCallStmt(pstate,
401  (CallStmt *) parseTree);
402  break;
403 
404  default:
405 
406  /*
407  * other statements don't require any transformation; just return
408  * the original parsetree with a Query node plastered on top.
409  */
410  result = makeNode(Query);
411  result->commandType = CMD_UTILITY;
412  result->utilityStmt = (Node *) parseTree;
413  break;
414  }
415 
416  /* Mark as original query until we learn differently */
417  result->querySource = QSRC_ORIGINAL;
418  result->canSetTag = true;
419 
420  return result;
421 }
Query * transformMergeStmt(ParseState *pstate, MergeStmt *stmt)
Definition: parse_merge.c:96
@ QSRC_ORIGINAL
Definition: parsenodes.h:43
static Query * transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
Definition: analyze.c:473
static Query * transformReturnStmt(ParseState *pstate, ReturnStmt *stmt)
Definition: analyze.c:2339
static Query * transformPLAssignStmt(ParseState *pstate, PLAssignStmt *stmt)
Definition: analyze.c:2565
static Query * transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
Definition: analyze.c:2959
static Query * transformCallStmt(ParseState *pstate, CallStmt *stmt)
Definition: analyze.c:3034
static Query * transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1651
static Query * transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
Definition: analyze.c:2370
static Query * transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1289
static Query * transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
Definition: analyze.c:2907
static Query * transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
Definition: analyze.c:2814
static Query * transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
Definition: analyze.c:544
static Query * transformValuesClause(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1432

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:236
int stmt_len
Definition: parsenodes.h:1849
int stmt_location
Definition: parsenodes.h:1848

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

2371 {
2372  Query *qry = makeNode(Query);
2373  ParseNamespaceItem *nsitem;
2374  Node *qual;
2375 
2376  qry->commandType = CMD_UPDATE;
2377  pstate->p_is_insert = false;
2378 
2379  /* process the WITH clause independently of all else */
2380  if (stmt->withClause)
2381  {
2382  qry->hasRecursive = stmt->withClause->recursive;
2383  qry->cteList = transformWithClause(pstate, stmt->withClause);
2384  qry->hasModifyingCTE = pstate->p_hasModifyingCTE;
2385  }
2386 
2387  qry->resultRelation = setTargetTable(pstate, stmt->relation,
2388  stmt->relation->inh,
2389  true,
2390  ACL_UPDATE);
2391  nsitem = pstate->p_target_nsitem;
2392 
2393  /* subqueries in FROM cannot access the result relation */
2394  nsitem->p_lateral_only = true;
2395  nsitem->p_lateral_ok = false;
2396 
2397  /*
2398  * the FROM clause is non-standard SQL syntax. We used to be able to do
2399  * this with REPLACE in POSTQUEL so we keep the feature.
2400  */
2401  transformFromClause(pstate, stmt->fromClause);
2402 
2403  /* remaining clauses can reference the result relation normally */
2404  nsitem->p_lateral_only = false;
2405  nsitem->p_lateral_ok = true;
2406 
2407  qual = transformWhereClause(pstate, stmt->whereClause,
2408  EXPR_KIND_WHERE, "WHERE");
2409 
2410  qry->returningList = transformReturningList(pstate, stmt->returningList);
2411 
2412  /*
2413  * Now we are done with SELECT-like processing, and can get on with
2414  * transforming the target list to match the UPDATE target columns.
2415  */
2416  qry->targetList = transformUpdateTargetList(pstate, stmt->targetList);
2417 
2418  qry->rtable = pstate->p_rtable;
2419  qry->rteperminfos = pstate->p_rteperminfos;
2420  qry->jointree = makeFromExpr(pstate->p_joinlist, qual);
2421 
2422  qry->hasTargetSRFs = pstate->p_hasTargetSRFs;
2423  qry->hasSubLinks = pstate->p_hasSubLinks;
2424 
2425  assign_query_collations(pstate, qry);
2426 
2427  return qry;
2428 }
@ CMD_UPDATE
Definition: nodes.h:277

References ACL_UPDATE, assign_query_collations(), CMD_UPDATE, Query::commandType, Query::cteList, EXPR_KIND_WHERE, Query::jointree, makeFromExpr(), makeNode, ParseState::p_hasModifyingCTE, ParseState::p_hasSubLinks, ParseState::p_hasTargetSRFs, ParseState::p_is_insert, ParseState::p_joinlist, ParseNamespaceItem::p_lateral_ok, ParseNamespaceItem::p_lateral_only, ParseState::p_rtable, ParseState::p_rteperminfos, ParseState::p_target_nsitem, Query::returningList, Query::rtable, setTargetTable(), stmt, Query::targetList, transformFromClause(), transformReturningList(), transformUpdateTargetList(), transformWhereClause(), and transformWithClause().

Referenced by transformStmt().

◆ transformUpdateTargetList()

List* transformUpdateTargetList ( ParseState pstate,
List origTlist 
)

Definition at line 2435 of file analyze.c.

2436 {
2437  List *tlist = NIL;
2438  RTEPermissionInfo *target_perminfo;
2439  ListCell *orig_tl;
2440  ListCell *tl;
2441 
2442  tlist = transformTargetList(pstate, origTlist,
2444 
2445  /* Prepare to assign non-conflicting resnos to resjunk attributes */
2448 
2449  /* Prepare non-junk columns for assignment to target table */
2450  target_perminfo = pstate->p_target_nsitem->p_perminfo;
2451  orig_tl = list_head(origTlist);
2452 
2453  foreach(tl, tlist)
2454  {
2455  TargetEntry *tle = (TargetEntry *) lfirst(tl);
2456  ResTarget *origTarget;
2457  int attrno;
2458 
2459  if (tle->resjunk)
2460  {
2461  /*
2462  * Resjunk nodes need no additional processing, but be sure they
2463  * have resnos that do not match any target columns; else rewriter
2464  * or planner might get confused. They don't need a resname
2465  * either.
2466  */
2467  tle->resno = (AttrNumber) pstate->p_next_resno++;
2468  tle->resname = NULL;
2469  continue;
2470  }
2471  if (orig_tl == NULL)
2472  elog(ERROR, "UPDATE target count mismatch --- internal error");
2473  origTarget = lfirst_node(ResTarget, orig_tl);
2474 
2475  attrno = attnameAttNum(pstate->p_target_relation,
2476  origTarget->name, true);
2477  if (attrno == InvalidAttrNumber)
2478  ereport(ERROR,
2479  (errcode(ERRCODE_UNDEFINED_COLUMN),
2480  errmsg("column \"%s\" of relation \"%s\" does not exist",
2481  origTarget->name,
2483  parser_errposition(pstate, origTarget->location)));
2484 
2485  updateTargetListEntry(pstate, tle, origTarget->name,
2486  attrno,
2487  origTarget->indirection,
2488  origTarget->location);
2489 
2490  /* Mark the target column as requiring update permissions */
2491  target_perminfo->updatedCols = bms_add_member(target_perminfo->updatedCols,
2493 
2494  orig_tl = lnext(origTlist, orig_tl);
2495  }
2496  if (orig_tl != NULL)
2497  elog(ERROR, "UPDATE target count mismatch --- internal error");
2498 
2499  return tlist;
2500 }
@ 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:537
Bitmapset * updatedCols
Definition: parsenodes.h:1250

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

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

◆ transformValuesClause()

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

Definition at line 1432 of file analyze.c.

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

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

Referenced by transformStmt().

Variable Documentation

◆ post_parse_analyze_hook