PlannedStmt *newnode = makeNode(PlannedStmt);
COPY_SCALAR_FIELD(commandType);
+ COPY_SCALAR_FIELD(queryId);
COPY_SCALAR_FIELD(hasReturning);
COPY_SCALAR_FIELD(hasModifyingCTE);
COPY_SCALAR_FIELD(canSetTag);
COPY_SCALAR_FIELD(commandType);
COPY_SCALAR_FIELD(querySource);
+ COPY_SCALAR_FIELD(queryId);
COPY_SCALAR_FIELD(canSetTag);
COPY_NODE_FIELD(utilityStmt);
COPY_SCALAR_FIELD(resultRelation);
{
COMPARE_SCALAR_FIELD(commandType);
COMPARE_SCALAR_FIELD(querySource);
+ /* we intentionally ignore queryId, since it might not be set */
COMPARE_SCALAR_FIELD(canSetTag);
COMPARE_NODE_FIELD(utilityStmt);
COMPARE_SCALAR_FIELD(resultRelation);
WRITE_NODE_TYPE("PLANNEDSTMT");
WRITE_ENUM_FIELD(commandType, CmdType);
+ WRITE_UINT_FIELD(queryId);
WRITE_BOOL_FIELD(hasReturning);
WRITE_BOOL_FIELD(hasModifyingCTE);
WRITE_BOOL_FIELD(canSetTag);
WRITE_ENUM_FIELD(commandType, CmdType);
WRITE_ENUM_FIELD(querySource, QuerySource);
+ /* we intentionally do not print the queryId field */
WRITE_BOOL_FIELD(canSetTag);
/*
READ_ENUM_FIELD(commandType, CmdType);
READ_ENUM_FIELD(querySource, QuerySource);
+ local_node->queryId = 0; /* not saved in output format */
READ_BOOL_FIELD(canSetTag);
READ_NODE_FIELD(utilityStmt);
READ_INT_FIELD(resultRelation);
result = makeNode(PlannedStmt);
result->commandType = parse->commandType;
+ result->queryId = parse->queryId;
result->hasReturning = (parse->returningList != NIL);
result->hasModifyingCTE = parse->hasModifyingCTE;
result->canSetTag = parse->canSetTag;
#include "utils/rel.h"
+/* Hook for plugins to get control at end of parse analysis */
+post_parse_analyze_hook_type post_parse_analyze_hook = NULL;
+
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
static List *transformInsertRow(ParseState *pstate, List *exprlist,
query = transformTopLevelStmt(pstate, parseTree);
+ if (post_parse_analyze_hook)
+ (*post_parse_analyze_hook) (pstate, query);
+
free_parsestate(pstate);
return query;
/* make sure all is well with parameter types */
check_variable_parameters(pstate, query);
+ if (post_parse_analyze_hook)
+ (*post_parse_analyze_hook) (pstate, query);
+
free_parsestate(pstate);
return query;
List *
QueryRewrite(Query *parsetree)
{
+ uint32 input_query_id = parsetree->queryId;
List *querylist;
List *results;
ListCell *l;
* Step 2
*
* Apply all the RIR rules on each query
+ *
+ * This is also a handy place to mark each query with the original queryId
*/
results = NIL;
foreach(l, querylist)
Query *query = (Query *) lfirst(l);
query = fireRIRrules(query, NIL, false);
+
+ query->queryId = input_query_id;
+
results = lappend(results, query);
}
query = transformTopLevelStmt(pstate, parsetree);
+ if (post_parse_analyze_hook)
+ (*post_parse_analyze_hook) (pstate, query);
+
free_parsestate(pstate);
if (log_parser_stats)
QuerySource querySource; /* where did I come from? */
+ uint32 queryId; /* query identifier (can be set by plugins) */
+
bool canSetTag; /* do I set the command result tag? */
Node *utilityStmt; /* non-null if this is DECLARE CURSOR or a
CmdType commandType; /* select|insert|update|delete */
+ uint32 queryId; /* query identifier (copied from Query) */
+
bool hasReturning; /* is it insert|update|delete RETURNING? */
bool hasModifyingCTE; /* has insert|update|delete in WITH? */
#include "parser/parse_node.h"
+/* Hook for plugins to get control at end of parse analysis */
+typedef void (*post_parse_analyze_hook_type) (ParseState *pstate,
+ Query *query);
+extern PGDLLIMPORT post_parse_analyze_hook_type post_parse_analyze_hook;
+
extern Query *parse_analyze(Node *parseTree, const char *sourceText,
Oid *paramTypes, int numParams);