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, 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

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

References nodeTag, result, 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().

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

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

2844 {
2845  RowMarkClause *rc;
2846 
2847  Assert(strength != LCS_NONE); /* else caller error */
2848 
2849  /* If it's an explicit clause, make sure hasForUpdate gets set */
2850  if (!pushedDown)
2851  qry->hasForUpdate = true;
2852 
2853  /* Check for pre-existing entry for same rtindex */
2854  if ((rc = get_parse_rowmark(qry, rtindex)) != NULL)
2855  {
2856  /*
2857  * If the same RTE is specified with more than one locking strength,
2858  * use the strongest. (Reasonable, since you can't take both a shared
2859  * and exclusive lock at the same time; it'll end up being exclusive
2860  * anyway.)
2861  *
2862  * Similarly, if the same RTE is specified with more than one lock
2863  * wait policy, consider that NOWAIT wins over SKIP LOCKED, which in
2864  * turn wins over waiting for the lock (the default). This is a bit
2865  * more debatable but raising an error doesn't seem helpful. (Consider
2866  * for instance SELECT FOR UPDATE NOWAIT from a view that internally
2867  * contains a plain FOR UPDATE spec.) Having NOWAIT win over SKIP
2868  * LOCKED is reasonable since the former throws an error in case of
2869  * coming across a locked tuple, which may be undesirable in some
2870  * cases but it seems better than silently returning inconsistent
2871  * results.
2872  *
2873  * And of course pushedDown becomes false if any clause is explicit.
2874  */
2875  rc->strength = Max(rc->strength, strength);
2876  rc->waitPolicy = Max(rc->waitPolicy, waitPolicy);
2877  rc->pushedDown &= pushedDown;
2878  return;
2879  }
2880 
2881  /* Make a new RowMarkClause */
2882  rc = makeNode(RowMarkClause);
2883  rc->rti = rtindex;
2884  rc->strength = strength;
2885  rc->waitPolicy = waitPolicy;
2886  rc->pushedDown = pushedDown;
2887  qry->rowMarks = lappend(qry->rowMarks, rc);
2888 }
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
List * rowMarks
Definition: parsenodes.h:161
LockClauseStrength strength
Definition: parsenodes.h:1283
List * lappend(List *list, void *datum)
Definition: list.c:128
#define Max(x, y)
Definition: c.h:800
#define makeNode(_type_)
Definition: nodes.h:557
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
LockWaitPolicy waitPolicy
Definition: parsenodes.h:1284
bool hasForUpdate
Definition: parsenodes.h:130
void CheckSelectLocking ( Query qry,
LockClauseStrength  strength 
)

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

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

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

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

Definition at line 96 of file analyze.c.

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

Referenced by DefineView(), and pg_analyze_and_rewrite().

99 {
100  ParseState *pstate = make_parsestate(NULL);
101  Query *query;
102 
103  Assert(sourceText != NULL); /* required as of 8.4 */
104 
105  pstate->p_sourcetext = sourceText;
106 
107  if (numParams > 0)
108  parse_fixed_parameters(pstate, paramTypes, numParams);
109 
110  pstate->p_queryEnv = queryEnv;
111 
112  query = transformTopLevelStmt(pstate, parseTree);
113 
115  (*post_parse_analyze_hook) (pstate, query);
116 
117  free_parsestate(pstate);
118 
119  return query;
120 }
QueryEnvironment * p_queryEnv
Definition: parse_node.h:192
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
const char * p_sourcetext
Definition: parse_node.h:168
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void parse_fixed_parameters(ParseState *pstate, Oid *paramTypes, int numParams)
Definition: parse_param.c:67
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:187
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
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 130 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().

132 {
133  ParseState *pstate = make_parsestate(NULL);
134  Query *query;
135 
136  Assert(sourceText != NULL); /* required as of 8.4 */
137 
138  pstate->p_sourcetext = sourceText;
139 
140  parse_variable_parameters(pstate, paramTypes, numParams);
141 
142  query = transformTopLevelStmt(pstate, parseTree);
143 
144  /* make sure all is well with parameter types */
145  check_variable_parameters(pstate, query);
146 
148  (*post_parse_analyze_hook) (pstate, query);
149 
150  free_parsestate(pstate);
151 
152  return query;
153 }
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:168
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Query * transformTopLevelStmt(ParseState *pstate, RawStmt *parseTree)
Definition: analyze.c:187
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:49
Query* parse_sub_analyze ( Node parseTree,
ParseState parentParseState,
CommonTableExpr parentCTE,
bool  locked_from_parent,
bool  resolve_unknowns 
)

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

164 {
165  ParseState *pstate = make_parsestate(parentParseState);
166  Query *query;
167 
168  pstate->p_parent_cte = parentCTE;
169  pstate->p_locked_from_parent = locked_from_parent;
170  pstate->p_resolve_unknowns = resolve_unknowns;
171 
172  query = transformStmt(pstate, parseTree);
173 
174  free_parsestate(pstate);
175 
176  return query;
177 }
CommonTableExpr * p_parent_cte
Definition: parse_node.h:178
bool p_locked_from_parent
Definition: parse_node.h:187
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
bool p_resolve_unknowns
Definition: parse_node.h:189
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:250
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
Query* transformStmt ( ParseState pstate,
Node parseTree 
)

Definition at line 250 of file analyze.c.

References Query::canSetTag, CMD_UTILITY, Query::commandType, makeNode, nodeTag, NULL, SelectStmt::op, QSRC_ORIGINAL, Query::querySource, result, 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().

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

Definition at line 187 of file analyze.c.

References result, 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().

188 {
189  Query *result;
190 
191  /* We're at top level, so allow SELECT INTO */
192  result = transformOptionalSelectInto(pstate, parseTree->stmt);
193 
194  result->stmt_location = parseTree->stmt_location;
195  result->stmt_len = parseTree->stmt_len;
196 
197  return result;
198 }
int stmt_location
Definition: parsenodes.h:180
return result
Definition: formatting.c:1632
Node * stmt
Definition: parsenodes.h:1400
int stmt_len
Definition: parsenodes.h:1402
int stmt_location
Definition: parsenodes.h:1401
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:211
int stmt_len
Definition: parsenodes.h:181

Variable Documentation