Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a40fa61

Browse files
committed
Add some infrastructure for contrib/pg_stat_statements.
Add a queryId field to Query and PlannedStmt. This is not used by the core backend, except for being copied around at appropriate times. It's meant to allow plug-ins to track a particular query forward from parse analysis to execution. The queryId is intentionally not dumped into stored rules (and hence this commit doesn't bump catversion). You could argue that choice either way, but it seems better that stored rule strings not have any dependency on plug-ins that might or might not be present. Also, add a post_parse_analyze_hook that gets invoked at the end of parse analysis (but only for top-level analysis of complete queries, not cases such as analyzing a domain's default-value expression). This is mainly meant to be used to compute and assign a queryId, but it could have other applications. Peter Geoghegan
1 parent 40b9b95 commit a40fa61

File tree

11 files changed

+34
-0
lines changed

11 files changed

+34
-0
lines changed

src/backend/nodes/copyfuncs.c

+2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ _copyPlannedStmt(const PlannedStmt *from)
7878
PlannedStmt *newnode = makeNode(PlannedStmt);
7979

8080
COPY_SCALAR_FIELD(commandType);
81+
COPY_SCALAR_FIELD(queryId);
8182
COPY_SCALAR_FIELD(hasReturning);
8283
COPY_SCALAR_FIELD(hasModifyingCTE);
8384
COPY_SCALAR_FIELD(canSetTag);
@@ -2402,6 +2403,7 @@ _copyQuery(const Query *from)
24022403

24032404
COPY_SCALAR_FIELD(commandType);
24042405
COPY_SCALAR_FIELD(querySource);
2406+
COPY_SCALAR_FIELD(queryId);
24052407
COPY_SCALAR_FIELD(canSetTag);
24062408
COPY_NODE_FIELD(utilityStmt);
24072409
COPY_SCALAR_FIELD(resultRelation);

src/backend/nodes/equalfuncs.c

+1
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,7 @@ _equalQuery(const Query *a, const Query *b)
897897
{
898898
COMPARE_SCALAR_FIELD(commandType);
899899
COMPARE_SCALAR_FIELD(querySource);
900+
/* we intentionally ignore queryId, since it might not be set */
900901
COMPARE_SCALAR_FIELD(canSetTag);
901902
COMPARE_NODE_FIELD(utilityStmt);
902903
COMPARE_SCALAR_FIELD(resultRelation);

src/backend/nodes/outfuncs.c

+2
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node)
242242
WRITE_NODE_TYPE("PLANNEDSTMT");
243243

244244
WRITE_ENUM_FIELD(commandType, CmdType);
245+
WRITE_UINT_FIELD(queryId);
245246
WRITE_BOOL_FIELD(hasReturning);
246247
WRITE_BOOL_FIELD(hasModifyingCTE);
247248
WRITE_BOOL_FIELD(canSetTag);
@@ -2152,6 +2153,7 @@ _outQuery(StringInfo str, const Query *node)
21522153

21532154
WRITE_ENUM_FIELD(commandType, CmdType);
21542155
WRITE_ENUM_FIELD(querySource, QuerySource);
2156+
/* we intentionally do not print the queryId field */
21552157
WRITE_BOOL_FIELD(canSetTag);
21562158

21572159
/*

src/backend/nodes/readfuncs.c

+1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ _readQuery(void)
195195

196196
READ_ENUM_FIELD(commandType, CmdType);
197197
READ_ENUM_FIELD(querySource, QuerySource);
198+
local_node->queryId = 0; /* not saved in output format */
198199
READ_BOOL_FIELD(canSetTag);
199200
READ_NODE_FIELD(utilityStmt);
200201
READ_INT_FIELD(resultRelation);

src/backend/optimizer/plan/planner.c

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
225225
result = makeNode(PlannedStmt);
226226

227227
result->commandType = parse->commandType;
228+
result->queryId = parse->queryId;
228229
result->hasReturning = (parse->returningList != NIL);
229230
result->hasModifyingCTE = parse->hasModifyingCTE;
230231
result->canSetTag = parse->canSetTag;

src/backend/parser/analyze.c

+9
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
#include "utils/rel.h"
4545

4646

47+
/* Hook for plugins to get control at end of parse analysis */
48+
post_parse_analyze_hook_type post_parse_analyze_hook = NULL;
49+
4750
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
4851
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
4952
static List *transformInsertRow(ParseState *pstate, List *exprlist,
@@ -95,6 +98,9 @@ parse_analyze(Node *parseTree, const char *sourceText,
9598

9699
query = transformTopLevelStmt(pstate, parseTree);
97100

101+
if (post_parse_analyze_hook)
102+
(*post_parse_analyze_hook) (pstate, query);
103+
98104
free_parsestate(pstate);
99105

100106
return query;
@@ -125,6 +131,9 @@ parse_analyze_varparams(Node *parseTree, const char *sourceText,
125131
/* make sure all is well with parameter types */
126132
check_variable_parameters(pstate, query);
127133

134+
if (post_parse_analyze_hook)
135+
(*post_parse_analyze_hook) (pstate, query);
136+
128137
free_parsestate(pstate);
129138

130139
return query;

src/backend/rewrite/rewriteHandler.c

+6
Original file line numberDiff line numberDiff line change
@@ -2157,6 +2157,7 @@ RewriteQuery(Query *parsetree, List *rewrite_events)
21572157
List *
21582158
QueryRewrite(Query *parsetree)
21592159
{
2160+
uint32 input_query_id = parsetree->queryId;
21602161
List *querylist;
21612162
List *results;
21622163
ListCell *l;
@@ -2181,13 +2182,18 @@ QueryRewrite(Query *parsetree)
21812182
* Step 2
21822183
*
21832184
* Apply all the RIR rules on each query
2185+
*
2186+
* This is also a handy place to mark each query with the original queryId
21842187
*/
21852188
results = NIL;
21862189
foreach(l, querylist)
21872190
{
21882191
Query *query = (Query *) lfirst(l);
21892192

21902193
query = fireRIRrules(query, NIL, false);
2194+
2195+
query->queryId = input_query_id;
2196+
21912197
results = lappend(results, query);
21922198
}
21932199

src/backend/tcop/postgres.c

+3
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,9 @@ pg_analyze_and_rewrite_params(Node *parsetree,
626626

627627
query = transformTopLevelStmt(pstate, parsetree);
628628

629+
if (post_parse_analyze_hook)
630+
(*post_parse_analyze_hook) (pstate, query);
631+
629632
free_parsestate(pstate);
630633

631634
if (log_parser_stats)

src/include/nodes/parsenodes.h

+2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ typedef struct Query
103103

104104
QuerySource querySource; /* where did I come from? */
105105

106+
uint32 queryId; /* query identifier (can be set by plugins) */
107+
106108
bool canSetTag; /* do I set the command result tag? */
107109

108110
Node *utilityStmt; /* non-null if this is DECLARE CURSOR or a

src/include/nodes/plannodes.h

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ typedef struct PlannedStmt
3737

3838
CmdType commandType; /* select|insert|update|delete */
3939

40+
uint32 queryId; /* query identifier (copied from Query) */
41+
4042
bool hasReturning; /* is it insert|update|delete RETURNING? */
4143

4244
bool hasModifyingCTE; /* has insert|update|delete in WITH? */

src/include/parser/analyze.h

+5
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616

1717
#include "parser/parse_node.h"
1818

19+
/* Hook for plugins to get control at end of parse analysis */
20+
typedef void (*post_parse_analyze_hook_type) (ParseState *pstate,
21+
Query *query);
22+
extern PGDLLIMPORT post_parse_analyze_hook_type post_parse_analyze_hook;
23+
1924

2025
extern Query *parse_analyze(Node *parseTree, const char *sourceText,
2126
Oid *paramTypes, int numParams);

0 commit comments

Comments
 (0)