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

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 }
Node * stmt
Definition: parsenodes.h:1431
#define nodeTag(nodeptr)
Definition: nodes.h:517

◆ applyLockingClause()

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

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

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

◆ CheckSelectLocking()

void CheckSelectLocking ( Query qry,
LockClauseStrength  strength 
)

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

2599 {
2600  Assert(strength != LCS_NONE); /* else caller error */
2601 
2602  if (qry->setOperations)
2603  ereport(ERROR,
2604  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2605  /*------
2606  translator: %s is a SQL row locking clause such as FOR UPDATE */
2607  errmsg("%s is not allowed with UNION/INTERSECT/EXCEPT",
2608  LCS_asString(strength))));
2609  if (qry->distinctClause != NIL)
2610  ereport(ERROR,
2611  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2612  /*------
2613  translator: %s is a SQL row locking clause such as FOR UPDATE */
2614  errmsg("%s is not allowed with DISTINCT clause",
2615  LCS_asString(strength))));
2616  if (qry->groupClause != NIL)
2617  ereport(ERROR,
2618  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2619  /*------
2620  translator: %s is a SQL row locking clause such as FOR UPDATE */
2621  errmsg("%s is not allowed with GROUP BY clause",
2622  LCS_asString(strength))));
2623  if (qry->havingQual != NULL)
2624  ereport(ERROR,
2625  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2626  /*------
2627  translator: %s is a SQL row locking clause such as FOR UPDATE */
2628  errmsg("%s is not allowed with HAVING clause",
2629  LCS_asString(strength))));
2630  if (qry->hasAggs)
2631  ereport(ERROR,
2632  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2633  /*------
2634  translator: %s is a SQL row locking clause such as FOR UPDATE */
2635  errmsg("%s is not allowed with aggregate functions",
2636  LCS_asString(strength))));
2637  if (qry->hasWindowFuncs)
2638  ereport(ERROR,
2639  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2640  /*------
2641  translator: %s is a SQL row locking clause such as FOR UPDATE */
2642  errmsg("%s is not allowed with window functions",
2643  LCS_asString(strength))));
2644  if (qry->hasTargetSRFs)
2645  ereport(ERROR,
2646  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2647  /*------
2648  translator: %s is a SQL row locking clause such as FOR UPDATE */
2649  errmsg("%s is not allowed with set-returning functions in the target list",
2650  LCS_asString(strength))));
2651 }
#define NIL
Definition: pg_list.h:69
const char * LCS_asString(LockClauseStrength strength)
Definition: analyze.c:2573
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 Assert(condition)
Definition: c.h:680
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

◆ LCS_asString()

const char* LCS_asString ( LockClauseStrength  strength)

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

2574 {
2575  switch (strength)
2576  {
2577  case LCS_NONE:
2578  Assert(false);
2579  break;
2580  case LCS_FORKEYSHARE:
2581  return "FOR KEY SHARE";
2582  case LCS_FORSHARE:
2583  return "FOR SHARE";
2584  case LCS_FORNOKEYUPDATE:
2585  return "FOR NO KEY UPDATE";
2586  case LCS_FORUPDATE:
2587  return "FOR UPDATE";
2588  }
2589  return "FOR some"; /* shouldn't happen */
2590 }
#define Assert(condition)
Definition: c.h:680

◆ parse_analyze()

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(), 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:196
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
const char * p_sourcetext
Definition: parse_node.h:172
#define Assert(condition)
Definition: c.h:680
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

◆ parse_analyze_varparams()

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(), 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:172
#define Assert(condition)
Definition: c.h:680
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

◆ parse_sub_analyze()

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:182
bool p_locked_from_parent
Definition: parse_node.h:191
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
bool p_resolve_unknowns
Definition: parse_node.h:193
Query * transformStmt(ParseState *pstate, Node *parseTree)
Definition: analyze.c:250
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77

◆ transformStmt()

Query* transformStmt ( ParseState pstate,
Node parseTree 
)

Definition at line 250 of file analyze.c.

References Query::canSetTag, CMD_UTILITY, Query::commandType, makeNode, nodeTag, 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().

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:2496
static Query * transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt)
Definition: analyze.c:2386
static Query * transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
Definition: analyze.c:2191
static Query * transformValuesClause(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1308
Definition: nodes.h:512
Node * utilityStmt
Definition: parsenodes.h:118
static Query * transformExplainStmt(ParseState *pstate, ExplainStmt *stmt)
Definition: analyze.c:2472
static Query * transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
Definition: analyze.c:1172
List * valuesLists
Definition: parsenodes.h:1535
static Query * transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
Definition: analyze.c:458
SetOperation op
Definition: parsenodes.h:1550
CmdType commandType
Definition: parsenodes.h:110
#define makeNode(_type_)
Definition: nodes.h:560
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:1546
#define nodeTag(nodeptr)
Definition: nodes.h:517

◆ transformTopLevelStmt()

Query* transformTopLevelStmt ( ParseState pstate,
RawStmt parseTree 
)

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

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:179
Node * stmt
Definition: parsenodes.h:1431
int stmt_len
Definition: parsenodes.h:1433
int stmt_location
Definition: parsenodes.h:1432
static Query * transformOptionalSelectInto(ParseState *pstate, Node *parseTree)
Definition: analyze.c:211
int stmt_len
Definition: parsenodes.h:180

Variable Documentation

◆ post_parse_analyze_hook