PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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)
 
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

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

Definition at line 20 of file analyze.h.

Function Documentation

bool analyze_requires_snapshot ( RawStmt parseTree)

Definition at line 345 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().

346 {
347  bool result;
348 
349  switch (nodeTag(parseTree->stmt))
350  {
351  /*
352  * Optimizable statements
353  */
354  case T_InsertStmt:
355  case T_DeleteStmt:
356  case T_UpdateStmt:
357  case T_SelectStmt:
358  result = true;
359  break;
360 
361  /*
362  * Special cases
363  */
364  case T_DeclareCursorStmt:
365  case T_ExplainStmt:
366  case T_CreateTableAsStmt:
367  /* yes, because we must analyze the contained statement */
368  result = true;
369  break;
370 
371  default:
372  /* other utility statements don't have any real parse analysis */
373  result = false;
374  break;
375  }
376 
377  return result;
378 }
Node * stmt
Definition: parsenodes.h:1337
#define nodeTag(nodeptr)
Definition: nodes.h:513
void applyLockingClause ( Query qry,
Index  rtindex,
LockClauseStrength  strength,
LockWaitPolicy  waitPolicy,
bool  pushedDown 
)

Definition at line 2818 of file analyze.c.

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

Referenced by markQueryForLocking(), and transformLockingClause().

2821 {
2822  RowMarkClause *rc;
2823 
2824  Assert(strength != LCS_NONE); /* else caller error */
2825 
2826  /* If it's an explicit clause, make sure hasForUpdate gets set */
2827  if (!pushedDown)
2828  qry->hasForUpdate = true;
2829 
2830  /* Check for pre-existing entry for same rtindex */
2831  if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
2832  {
2833  /*
2834  * If the same RTE is specified with more than one locking strength,
2835  * use the strongest. (Reasonable, since you can't take both a shared
2836  * and exclusive lock at the same time; it'll end up being exclusive
2837  * anyway.)
2838  *
2839  * Similarly, if the same RTE is specified with more than one lock
2840  * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
2841  * turn wins over waiting for the lock (the default). This is a bit
2842  * more debatable but raising an error doesn't seem helpful. (Consider
2843  * for instance SELECT FOR UPDATE NOWAIT from a view that internally
2844  * contains a plain FOR UPDATE spec.) Having NOWAIT win over SKIP
2845  * LOCKED is reasonable since the former throws an error in case of
2846  * coming across a locked tuple, which may be undesirable in some
2847  * cases but it seems better than silently returning inconsistent
2848  * results.
2849  *
2850  * And of course pushedDown becomes false if any clause is explicit.
2851  */
2852  rc->strength = Max(rc->strength, strength);
2853  rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
2854  rc->pushedDown &= pushedDown;
2855  return;
2856  }
2857 
2858  /* Make a new RowMarkClause */
2859  rc = makeNode(RowMarkClause);
2860  rc->rti = rtindex;
2861  rc->strength = strength;
2862  rc->waitPolicy = waitPolicy;
2863  rc->pushedDown = pushedDown;
2864  qry->rowMarks = lappend(qry->rowMarks, rc);
2865 }
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
List * rowMarks
Definition: parsenodes.h:152
LockClauseStrength strength
Definition: parsenodes.h:1220
List * lappend(List *list, void *datum)
Definition: list.c:128
#define Max(x, y)
Definition: c.h:796
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1221
bool hasForUpdate
Definition: parsenodes.h:123
void CheckSelectLocking ( Query qry,
LockClauseStrength  strength 
)

Definition at line 2601 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, NULL, and Query::setOperations.

Referenced by preprocess_rowmarks(), and transformLockingClause().

2602 {
2603  Assert(strength != LCS_NONE); /* else caller error */
2604 
2605  if (qry->setOperations)
2606  ereport(ERROR,
2607  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2608  /*------
2609  translator: %s is a SQL row locking clause such as FOR UPDATE */
2610  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
2611  LCS_asString(strength))));
2612  if (qry->distinctClause != NIL)
2613  ereport(ERROR,
2614  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2615  /*------
2616  translator: %s is a SQL row locking clause such as FOR UPDATE */
2617  errmsg("%s is not allowed with DISTINCT clause",
2618  LCS_asString(strength))));
2619  if (qry->groupClause != NIL)
2620  ereport(ERROR,
2621  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2622  /*------
2623  translator: %s is a SQL row locking clause such as FOR UPDATE */
2624  errmsg("%s is not allowed with GROUP BY clause",
2625  LCS_asString(strength))));
2626  if (qry->havingQual != NULL)
2627  ereport(ERROR,
2628  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2629  /*------
2630  translator: %s is a SQL row locking clause such as FOR UPDATE */
2631  errmsg("%s is not allowed with HAVING clause",
2632  LCS_asString(strength))));
2633  if (qry->hasAggs)
2634  ereport(ERROR,
2635  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2636  /*------
2637  translator: %s is a SQL row locking clause such as FOR UPDATE */
2638  errmsg("%s is not allowed with aggregate functions",
2639  LCS_asString(strength))));
2640  if (qry->hasWindowFuncs)
2641  ereport(ERROR,
2642  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2643  /*------
2644  translator: %s is a SQL row locking clause such as FOR UPDATE */
2645  errmsg("%s is not allowed with window functions",
2646  LCS_asString(strength))));
2647  if (qry->hasTargetSRFs)
2648  ereport(ERROR,
2649  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2650  /*------
2651  translator: %s is a SQL row locking clause such as FOR UPDATE */
2652  errmsg("%s is not allowed with set-returning functions in the target list",
2653  LCS_asString(strength))));
2654 }
#define NIL
Definition: pg_list.h:69
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2576
bool hasAggs
Definition: parsenodes.h:116
int errcode(int sqlerrcode)
Definition: elog.c:575
List * distinctClause
Definition: parsenodes.h:145
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool hasTargetSRFs
Definition: parsenodes.h:118
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
bool hasWindowFuncs
Definition: parsenodes.h:117
Node * setOperations
Definition: parsenodes.h:154
List * groupClause
Definition: parsenodes.h:137
int errmsg(const char *fmt,...)
Definition: elog.c:797
Node * havingQual
Definition: parsenodes.h:141
const char* LCS_asString ( LockClauseStrength  strength)

Definition at line 2576 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().

2577 {
2578  switch (strength)
2579  {
2580  case LCS_NONE:
2581  Assert(false);
2582  break;
2583  case LCS_FORKEYSHARE:
2584  return "FOR KEY SHARE";
2585  case LCS_FORSHARE:
2586  return "FOR SHARE";
2587  case LCS_FORNOKEYUPDATE:
2588  return "FOR NO KEY UPDATE";
2589  case LCS_FORUPDATE:
2590  return "FOR UPDATE";
2591  }
2592  return "FOR some"; /* shouldn't happen */
2593 }
#define Assert(condition)
Definition: c.h:671
Query* parse_analyze ( RawStmt parseTree,
const char *  sourceText,
Oid paramTypes,
int  numParams 
)

Definition at line 96 of file analyze.c.

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

Referenced by DefineView(), and pg_analyze_and_rewrite().

98 {
99  ParseState *pstate = make_parsestate(NULL);
100  Query *query;
101 
102  Assert(sourceText != NULL); /* required as of 8.4 */
103 
104  pstate->p_sourcetext = sourceText;
105 
106  if (numParams > 0)
107  parse_fixed_parameters(pstate, paramTypes, numParams);
108 
109  query = transformTopLevelStmt(pstate, parseTree);
110 
112  (*post_parse_analyze_hook) (pstate, query);
113 
114  free_parsestate(pstate);
115 
116  return query;
117 }
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
const char * p_sourcetext
Definition: parse_node.h:167
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void parse_fixed_parameters(ParseState *pstate, Oid *paramTypes, int numParams)
Definition: parse_param.c:67
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:184
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:75
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:49
Query* parse_analyze_varparams ( RawStmt parseTree,
const char *  sourceText,
Oid **  paramTypes,
int *  numParams 
)

Definition at line 127 of file analyze.c.

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

Referenced by exec_parse_message(), and PrepareQuery().

129 {
130  ParseState *pstate = make_parsestate(NULL);
131  Query *query;
132 
133  Assert(sourceText != NULL); /* required as of 8.4 */
134 
135  pstate->p_sourcetext = sourceText;
136 
137  parse_variable_parameters(pstate, paramTypes, numParams);
138 
139  query = transformTopLevelStmt(pstate, parseTree);
140 
141  /* make sure all is well with parameter types */
142  check_variable_parameters(pstate, query);
143 
145  (*post_parse_analyze_hook) (pstate, query);
146 
147  free_parsestate(pstate);
148 
149  return query;
150 }
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:167
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:184
void check_variable_parameters(ParseState *pstate, Query *query)
Definition: parse_param.c:263
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:75
post_parse_analyze_hook_type post_parse_analyze_hook
Definition: analyze.c:49
Query* parse_sub_analyze ( Node parseTree,
ParseState parentParseState,
CommonTableExpr parentCTE,
bool  locked_from_parent,
bool  resolve_unknowns 
)

Definition at line 157 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().

161 {
162  ParseState *pstate = make_parsestate(parentParseState);
163  Query *query;
164 
165  pstate->p_parent_cte = parentCTE;
166  pstate->p_locked_from_parent = locked_from_parent;
167  pstate->p_resolve_unknowns = resolve_unknowns;
168 
169  query = transformStmt(pstate, parseTree);
170 
171  free_parsestate(pstate);
172 
173  return query;
174 }
CommonTableExpr * p_parent_cte
Definition: parse_node.h:177
bool p_locked_from_parent
Definition: parse_node.h:186
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
bool p_resolve_unknowns
Definition: parse_node.h:188
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:247
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:75
Query* transformStmt ( ParseState pstate,
Node parseTree 
)

Definition at line 247 of file analyze.c.

References Query::canSetTag, CMD_UTILITY, Query::commandType, makeNode, nodeTag, NULL, SelectStmt::op, QSRC_ORIGINAL, Query::querySource, SETOP_NONE, T_CreateTableAsStmt, T_DeclareCursorStmt, T_DeleteStmt, T_ExplainStmt, T_InsertStmt, T_SelectStmt, T_UpdateStmt, 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().

248 {
249  Query *result;
250 
251  /*
252  * We apply RAW_EXPRESSION_COVERAGE_TEST testing to basic DML statements;
253  * we can't just run it on everything because raw_expression_tree_walker()
254  * doesn't claim to handle utility statements.
255  */
256 #ifdef RAW_EXPRESSION_COVERAGE_TEST
257  switch (nodeTag(parseTree))
258  {
259  case T_SelectStmt:
260  case T_InsertStmt:
261  case T_UpdateStmt:
262  case T_DeleteStmt:
263  (void) test_raw_expression_coverage(parseTree, NULL);
264  break;
265  default:
266  break;
267  }
268 #endif /* RAW_EXPRESSION_COVERAGE_TEST */
269 
270  switch (nodeTag(parseTree))
271  {
272  /*
273  * Optimizable statements
274  */
275  case T_InsertStmt:
276  result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
277  break;
278 
279  case T_DeleteStmt:
280  result = transformDeleteStmt(pstate, (DeleteStmt *) parseTree);
281  break;
282 
283  case T_UpdateStmt:
284  result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
285  break;
286 
287  case T_SelectStmt:
288  {
289  SelectStmt *n = (SelectStmt *) parseTree;
290 
291  if (n->valuesLists)
292  result = transformValuesClause(pstate, n);
293  else if (n->op == SETOP_NONE)
294  result = transformSelectStmt(pstate, n);
295  else
296  result = transformSetOperationStmt(pstate, n);
297  }
298  break;
299 
300  /*
301  * Special cases
302  */
303  case T_DeclareCursorStmt:
304  result = transformDeclareCursorStmt(pstate,
305  (DeclareCursorStmt *) parseTree);
306  break;
307 
308  case T_ExplainStmt:
309  result = transformExplainStmt(pstate,
310  (ExplainStmt *) parseTree);
311  break;
312 
313  case T_CreateTableAsStmt:
314  result = transformCreateTableAsStmt(pstate,
315  (CreateTableAsStmt *) parseTree);
316  break;
317 
318  default:
319 
320  /*
321  * other statements don't require any transformation; just return
322  * the original parsetree with a Query node plastered on top.
323  */
324  result = makeNode(Query);
325  result->commandType = CMD_UTILITY;
326  result->utilityStmt = (Node *) parseTree;
327  break;
328  }
329 
330  /* Mark as original query until we learn differently */
331  result->querySource = QSRC_ORIGINAL;
332  result->canSetTag = true;
333 
334  return result;
335 }
static Query * transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
Definition: analyze.c:2499
static Query * transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
Definition: analyze.c:2389
static Query * transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
Definition: analyze.c:2194
static Query * transformValuesClause(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1311
Definition: nodes.h:508
Node * utilityStmt
Definition: parsenodes.h:111
static Query * transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
Definition: analyze.c:2475
static Query * transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1175
List * valuesLists
Definition: parsenodes.h:1440
static Query * transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
Definition: analyze.c:455
SetOperation op
Definition: parsenodes.h:1455
CmdType commandType
Definition: parsenodes.h:103
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
QuerySource querySource
Definition: parsenodes.h:105
bool canSetTag
Definition: parsenodes.h:109
static Query * transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
Definition: analyze.c:385
static Query * transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1549
#define nodeTag(nodeptr)
Definition: nodes.h:513
Query* transformTopLevelStmt ( ParseState pstate,
RawStmt parseTree 
)

Definition at line 184 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().

185 {
186  Query *result;
187 
188  /* We're at top level, so allow SELECT INTO */
189  result = transformOptionalSelectInto(pstate, parseTree->stmt);
190 
191  result->stmt_location = parseTree->stmt_location;
192  result->stmt_len = parseTree->stmt_len;
193 
194  return result;
195 }
int stmt_location
Definition: parsenodes.h:171
Node * stmt
Definition: parsenodes.h:1337
int stmt_len
Definition: parsenodes.h:1339
int stmt_location
Definition: parsenodes.h:1338
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:208
int stmt_len
Definition: parsenodes.h:172

Variable Documentation