PostgreSQL Source Code  git master
analyze.h File Reference
Include dependency graph for analyze.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef void(* post_parse_analyze_hook_type) (ParseState *pstate, Query *query)
 

Functions

Queryparse_analyze (RawStmt *parseTree, const char *sourceText, Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
 
Queryparse_analyze_varparams (RawStmt *parseTree, const char *sourceText, Oid **paramTypes, int *numParams)
 
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)
 
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

PGDLLIMPORT post_parse_analyze_hook_type post_parse_analyze_hook
 

Typedef Documentation

◆ post_parse_analyze_hook_type

typedef void(* post_parse_analyze_hook_type) (ParseState *pstate, Query *query)

Definition at line 20 of file analyze.h.

Function Documentation

◆ analyze_requires_snapshot()

bool analyze_requires_snapshot ( RawStmt parseTree)

Definition at line 357 of file analyze.c.

References nodeTag, RawStmt::stmt, T_CreateTableAsStmt, T_DeclareCursorStmt, T_DeleteStmt, T_ExplainStmt, T_InsertStmt, T_SelectStmt, and T_UpdateStmt.

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

358 {
359  bool result;
360 
361  switch (nodeTag(parseTree->stmt))
362  {
363  /*
364  * Optimizable statements
365  */
366  case T_InsertStmt:
367  case T_DeleteStmt:
368  case T_UpdateStmt:
369  case T_SelectStmt:
370  result = true;
371  break;
372 
373  /*
374  * Special cases
375  */
376  case T_DeclareCursorStmt:
377  case T_ExplainStmt:
378  case T_CreateTableAsStmt:
379  /* yes, because we must analyze the contained statement */
380  result = true;
381  break;
382 
383  default:
384  /* other utility statements don't have any real parse analysis */
385  result = false;
386  break;
387  }
388 
389  return result;
390 }
Node * stmt
Definition: parsenodes.h:1450
#define nodeTag(nodeptr)
Definition: nodes.h:522

◆ applyLockingClause()

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

Definition at line 2879 of file analyze.c.

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

Referenced by markQueryForLocking(), and transformLockingClause().

2882 {
2883  RowMarkClause *rc;
2884 
2885  Assert(strength != LCS_NONE); /* else caller error */
2886 
2887  /* If it's an explicit clause, make sure hasForUpdate gets set */
2888  if (!pushedDown)
2889  qry->hasForUpdate = true;
2890 
2891  /* Check for pre-existing entry for same rtindex */
2892  if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
2893  {
2894  /*
2895  * If the same RTE is specified with more than one locking strength,
2896  * use the strongest. (Reasonable, since you can't take both a shared
2897  * and exclusive lock at the same time; it'll end up being exclusive
2898  * anyway.)
2899  *
2900  * Similarly, if the same RTE is specified with more than one lock
2901  * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
2902  * turn wins over waiting for the lock (the default). This is a bit
2903  * more debatable but raising an error doesn't seem helpful. (Consider
2904  * for instance SELECT FOR UPDATE NOWAIT from a view that internally
2905  * contains a plain FOR UPDATE spec.) Having NOWAIT win over SKIP
2906  * LOCKED is reasonable since the former throws an error in case of
2907  * coming across a locked tuple, which may be undesirable in some
2908  * cases but it seems better than silently returning inconsistent
2909  * results.
2910  *
2911  * And of course pushedDown becomes false if any clause is explicit.
2912  */
2913  rc->strength = Max(rc->strength, strength);
2914  rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
2915  rc->pushedDown &= pushedDown;
2916  return;
2917  }
2918 
2919  /* Make a new RowMarkClause */
2920  rc = makeNode(RowMarkClause);
2921  rc->rti = rtindex;
2922  rc->strength = strength;
2923  rc->waitPolicy = waitPolicy;
2924  rc->pushedDown = pushedDown;
2925  qry->rowMarks = lappend(qry->rowMarks, rc);
2926 }
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
List * rowMarks
Definition: parsenodes.h:163
LockClauseStrength strength
Definition: parsenodes.h:1333
List * lappend(List *list, void *datum)
Definition: list.c:128
#define Max(x, y)
Definition: c.h:851
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1334
bool hasForUpdate
Definition: parsenodes.h:132

◆ CheckSelectLocking()

void CheckSelectLocking ( Query qry,
LockClauseStrength  strength 
)

Definition at line 2644 of file analyze.c.

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

Referenced by preprocess_rowmarks(), and transformLockingClause().

2645 {
2646  Assert(strength != LCS_NONE); /* else caller error */
2647 
2648  if (qry->setOperations)
2649  ereport(ERROR,
2650  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2651  /*------
2652  translator: %s is a SQL row locking clause such as FOR UPDATE */
2653  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
2654  LCS_asString(strength))));
2655  if (qry->distinctClause != NIL)
2656  ereport(ERROR,
2657  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2658  /*------
2659  translator: %s is a SQL row locking clause such as FOR UPDATE */
2660  errmsg("%s is not allowed with DISTINCT clause",
2661  LCS_asString(strength))));
2662  if (qry->groupClause != NIL)
2663  ereport(ERROR,
2664  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2665  /*------
2666  translator: %s is a SQL row locking clause such as FOR UPDATE */
2667  errmsg("%s is not allowed with GROUP BY clause",
2668  LCS_asString(strength))));
2669  if (qry->havingQual != NULL)
2670  ereport(ERROR,
2671  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2672  /*------
2673  translator: %s is a SQL row locking clause such as FOR UPDATE */
2674  errmsg("%s is not allowed with HAVING clause",
2675  LCS_asString(strength))));
2676  if (qry->hasAggs)
2677  ereport(ERROR,
2678  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2679  /*------
2680  translator: %s is a SQL row locking clause such as FOR UPDATE */
2681  errmsg("%s is not allowed with aggregate functions",
2682  LCS_asString(strength))));
2683  if (qry->hasWindowFuncs)
2684  ereport(ERROR,
2685  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2686  /*------
2687  translator: %s is a SQL row locking clause such as FOR UPDATE */
2688  errmsg("%s is not allowed with window functions",
2689  LCS_asString(strength))));
2690  if (qry->hasTargetSRFs)
2691  ereport(ERROR,
2692  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2693  /*------
2694  translator: %s is a SQL row locking clause such as FOR UPDATE */
2695  errmsg("%s is not allowed with set-returning functions in the target list",
2696  LCS_asString(strength))));
2697 }
#define NIL
Definition: pg_list.h:69
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2619
bool hasAggs
Definition: parsenodes.h:125
int errcode(int sqlerrcode)
Definition: elog.c:575
List * distinctClause
Definition: parsenodes.h:156
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool hasTargetSRFs
Definition: parsenodes.h:127
#define Assert(condition)
Definition: c.h:699
bool hasWindowFuncs
Definition: parsenodes.h:126
Node * setOperations
Definition: parsenodes.h:165
List * groupClause
Definition: parsenodes.h:148
int errmsg(const char *fmt,...)
Definition: elog.c:797
Node * havingQual
Definition: parsenodes.h:152

◆ LCS_asString()

const char* LCS_asString ( LockClauseStrength  strength)

Definition at line 2619 of file analyze.c.

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

2620 {
2621  switch (strength)
2622  {
2623  case LCS_NONE:
2624  Assert(false);
2625  break;
2626  case LCS_FORKEYSHARE:
2627  return "FOR KEY SHARE";
2628  case LCS_FORSHARE:
2629  return "FOR SHARE";
2630  case LCS_FORNOKEYUPDATE:
2631  return "FOR NO KEY UPDATE";
2632  case LCS_FORUPDATE:
2633  return "FOR UPDATE";
2634  }
2635  return "FOR some"; /* shouldn't happen */
2636 }
#define Assert(condition)
Definition: c.h:699

◆ parse_analyze()

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

Definition at line 100 of file analyze.c.

References Assert, free_parsestate(), make_parsestate(), ParseState::p_queryEnv, ParseState::p_sourcetext, parse_fixed_parameters(), post_parse_analyze_hook, and transformTopLevelStmt().

Referenced by DefineView(), and pg_analyze_and_rewrite().

103 {
104  ParseState *pstate = make_parsestate(NULL);
105  Query *query;
106 
107  Assert(sourceText != NULL); /* required as of 8.4 */
108 
109  pstate->p_sourcetext = sourceText;
110 
111  if (numParams > 0)
112  parse_fixed_parameters(pstate, paramTypes, numParams);
113 
114  pstate->p_queryEnv = queryEnv;
115 
116  query = transformTopLevelStmt(pstate, parseTree);
117 
119  (*post_parse_analyze_hook) (pstate, query);
120 
121  free_parsestate(pstate);
122 
123  return query;
124 }
QueryEnvironment * p_queryEnv
Definition: parse_node.h:197
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
const char * p_sourcetext
Definition: parse_node.h:173
#define Assert(condition)
Definition: c.h:699
void parse_fixed_parameters(ParseState *pstate, Oid *paramTypes, int numParams)
Definition: parse_param.c:67
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:191
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:51

◆ parse_analyze_varparams()

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

Definition at line 134 of file analyze.c.

References Assert, check_variable_parameters(), free_parsestate(), make_parsestate(), ParseState::p_sourcetext, parse_variable_parameters(), post_parse_analyze_hook, and transformTopLevelStmt().

Referenced by exec_parse_message(), and PrepareQuery().

136 {
137  ParseState *pstate = make_parsestate(NULL);
138  Query *query;
139 
140  Assert(sourceText != NULL); /* required as of 8.4 */
141 
142  pstate->p_sourcetext = sourceText;
143 
144  parse_variable_parameters(pstate, paramTypes, numParams);
145 
146  query = transformTopLevelStmt(pstate, parseTree);
147 
148  /* make sure all is well with parameter types */
149  check_variable_parameters(pstate, query);
150 
152  (*post_parse_analyze_hook) (pstate, query);
153 
154  free_parsestate(pstate);
155 
156  return query;
157 }
void parse_variable_parameters(ParseState *pstate, Oid **paramTypes, int *numParams)
Definition: parse_param.c:83
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
const char * p_sourcetext
Definition: parse_node.h:173
#define Assert(condition)
Definition: c.h:699
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:191
void check_variable_parameters(ParseState *pstate, Query *query)
Definition: parse_param.c:263
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:51

◆ parse_sub_analyze()

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

Definition at line 164 of file analyze.c.

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

168 {
169  ParseState *pstate = make_parsestate(parentParseState);
170  Query *query;
171 
172  pstate->p_parent_cte = parentCTE;
173  pstate->p_locked_from_parent = locked_from_parent;
174  pstate->p_resolve_unknowns = resolve_unknowns;
175 
176  query = transformStmt(pstate, parseTree);
177 
178  free_parsestate(pstate);
179 
180  return query;
181 }
CommonTableExpr * p_parent_cte
Definition: parse_node.h:183
bool p_locked_from_parent
Definition: parse_node.h:192
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
bool p_resolve_unknowns
Definition: parse_node.h:194
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:254
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77

◆ transformStmt()

Query* transformStmt ( ParseState pstate,
Node parseTree 
)

Definition at line 254 of file analyze.c.

References Query::canSetTag, CMD_UTILITY, Query::commandType, makeNode, nodeTag, SelectStmt::op, QSRC_ORIGINAL, Query::querySource, SETOP_NONE, T_CallStmt, T_CreateTableAsStmt, T_DeclareCursorStmt, T_DeleteStmt, T_ExplainStmt, T_InsertStmt, T_SelectStmt, T_UpdateStmt, transformCallStmt(), transformCreateTableAsStmt(), transformDeclareCursorStmt(), transformDeleteStmt(), transformExplainStmt(), transformInsertStmt(), transformSelectStmt(), transformSetOperationStmt(), transformUpdateStmt(), transformValuesClause(), Query::utilityStmt, and SelectStmt::valuesLists.

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

255 {
256  Query *result;
257 
258  /*
259  * We apply RAW_EXPRESSION_COVERAGE_TEST testing to basic DML statements;
260  * we can't just run it on everything because raw_expression_tree_walker()
261  * doesn't claim to handle utility statements.
262  */
263 #ifdef RAW_EXPRESSION_COVERAGE_TEST
264  switch (nodeTag(parseTree))
265  {
266  case T_SelectStmt:
267  case T_InsertStmt:
268  case T_UpdateStmt:
269  case T_DeleteStmt:
270  (void) test_raw_expression_coverage(parseTree, NULL);
271  break;
272  default:
273  break;
274  }
275 #endif /* RAW_EXPRESSION_COVERAGE_TEST */
276 
277  switch (nodeTag(parseTree))
278  {
279  /*
280  * Optimizable statements
281  */
282  case T_InsertStmt:
283  result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
284  break;
285 
286  case T_DeleteStmt:
287  result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
288  break;
289 
290  case T_UpdateStmt:
291  result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
292  break;
293 
294  case T_SelectStmt:
295  {
296  SelectStmt *n = (SelectStmt *) parseTree;
297 
298  if (n->valuesLists)
299  result = transformValuesClause(pstate, n);
300  else if (n->op == SETOP_NONE)
301  result = transformSelectStmt(pstate, n);
302  else
303  result = transformSetOperationStmt(pstate, n);
304  }
305  break;
306 
307  /*
308  * Special cases
309  */
310  case T_DeclareCursorStmt:
311  result = transformDeclareCursorStmt(pstate,
312  (DeclareCursorStmt *) parseTree);
313  break;
314 
315  case T_ExplainStmt:
316  result = transformExplainStmt(pstate,
317  (ExplainStmt *) parseTree);
318  break;
319 
320  case T_CreateTableAsStmt:
321  result = transformCreateTableAsStmt(pstate,
322  (CreateTableAsStmt *) parseTree);
323  break;
324 
325  case T_CallStmt:
326  result = transformCallStmt(pstate,
327  (CallStmt *) parseTree);
328  break;
329 
330  default:
331 
332  /*
333  * other statements don't require any transformation; just return
334  * the original parsetree with a Query node plastered on top.
335  */
336  result = makeNode(Query);
337  result->commandType = CMD_UTILITY;
338  result->utilityStmt = (Node *) parseTree;
339  break;
340  }
341 
342  /* Mark as original query until we learn differently */
343  result->querySource = QSRC_ORIGINAL;
344  result->canSetTag = true;
345 
346  return result;
347 }
static Query * transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
Definition: analyze.c:2505
static Query * transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
Definition: analyze.c:2395
static Query * transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
Definition: analyze.c:2200
static Query * transformValuesClause(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1317
Definition: nodes.h:517
Node * utilityStmt
Definition: parsenodes.h:120
static Query * transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
Definition: analyze.c:2481
static Query * transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1181
List * valuesLists
Definition: parsenodes.h:1554
static Query * transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
Definition: analyze.c:467
SetOperation op
Definition: parsenodes.h:1569
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:565
QuerySource querySource
Definition: parsenodes.h:114
bool canSetTag
Definition: parsenodes.h:118
static Query * transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
Definition: analyze.c:397
static Query * transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1555
#define nodeTag(nodeptr)
Definition: nodes.h:522
static Query * transformCallStmt(ParseState *pstate, CallStmt *stmt)
Definition: analyze.c:2582

◆ transformTopLevelStmt()

Query* transformTopLevelStmt ( ParseState pstate,
RawStmt parseTree 
)

Definition at line 191 of file analyze.c.

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

Referenced by inline_function(), parse_analyze(), parse_analyze_varparams(), and pg_analyze_and_rewrite_params().

192 {
193  Query *result;
194 
195  /* We're at top level, so allow SELECT INTO */
196  result = transformOptionalSelectInto(pstate, parseTree->stmt);
197 
198  result->stmt_location = parseTree->stmt_location;
199  result->stmt_len = parseTree->stmt_len;
200 
201  return result;
202 }
int stmt_location
Definition: parsenodes.h:181
Node * stmt
Definition: parsenodes.h:1450
int stmt_len
Definition: parsenodes.h:1452
int stmt_location
Definition: parsenodes.h:1451
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:215
int stmt_len
Definition: parsenodes.h:182

Variable Documentation

◆ post_parse_analyze_hook