0001-Add-new-EXPLAIN-options-plan-and-rewrite.patch
text/x-patch
Filename: 0001-Add-new-EXPLAIN-options-plan-and-rewrite.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0001
Subject: Add new EXPLAIN options "plan" and "rewrite"
| File | + | − |
|---|---|---|
| src/backend/commands/explain.c | 41 | 15 |
| src/include/commands/explain.h | 2 | 0 |
From c5251309a3eb3e826eab9bf792d4ba84fca63738 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 9 Nov 2011 17:52:38 +0100
Subject: [PATCH] Add new EXPLAIN options "plan" and "rewrite"
Those commands are useful to make it easier to gauge the costs of those
respective steps when introducing new features or optimizing existing code.
Another useful thing would be to be able to separate the parse and
parse-analyze steps, but that is more invasive.
---
src/backend/commands/explain.c | 56 +++++++++++++++++++++++++++++----------
src/include/commands/explain.h | 2 +
2 files changed, 43 insertions(+), 15 deletions(-)
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index e38de5c..2987d3b 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -133,6 +133,10 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
es.costs = defGetBoolean(opt);
else if (strcmp(opt->defname, "buffers") == 0)
es.buffers = defGetBoolean(opt);
+ else if (strcmp(opt->defname, "plan") == 0)
+ es.plan = defGetBoolean(opt);
+ else if (strcmp(opt->defname, "rewrite") == 0)
+ es.rewrite = defGetBoolean(opt);
else if (strcmp(opt->defname, "format") == 0)
{
char *p = defGetString(opt);
@@ -158,11 +162,25 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
opt->defname)));
}
+
if (es.buffers && !es.analyze)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("EXPLAIN option BUFFERS requires ANALYZE")));
+ if ((!es.plan || !es.rewrite) && es.analyze)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("EXPLAIN option !PLAN contradicts ANALYZE")));
+ /*
+ * XXX: we could check for !plan && rewrite but that would mean !rewrite
+ * would have to explicitly specified when disabling planning...
+ */
+
+ /* emit opening boilerplate */
+ ExplainBeginOutput(&es);
+
+ Assert(IsA(stmt->query, Query));
/*
* Parse analysis was done already, but we still have to run the rule
* rewriter. We do not do AcquireRewriteLocks: we assume the query either
@@ -175,11 +193,13 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
* executed repeatedly. (See also the same hack in DECLARE CURSOR and
* PREPARE.) XXX FIXME someday.
*/
- Assert(IsA(stmt->query, Query));
- rewritten = QueryRewrite((Query *) copyObject(stmt->query));
+ if(!es.rewrite){
+ if (es.format == EXPLAIN_FORMAT_TEXT)
+ appendStringInfoString(es.str, "not rewriting query because auf !rewrite\n");
+ goto out;
+ }
- /* emit opening boilerplate */
- ExplainBeginOutput(&es);
+ rewritten = QueryRewrite((Query *) copyObject(stmt->query));
if (rewritten == NIL)
{
@@ -189,22 +209,26 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
*/
if (es.format == EXPLAIN_FORMAT_TEXT)
appendStringInfoString(es.str, "Query rewrites to nothing\n");
+ goto out;
}
- else
- {
- ListCell *l;
- /* Explain every plan */
- foreach(l, rewritten)
- {
- ExplainOneQuery((Query *) lfirst(l), &es, queryString, params);
+ if(!es.plan){
+ if (es.format == EXPLAIN_FORMAT_TEXT)
+ appendStringInfoString(es.str, "not planning or rewriting query because !plan\n");
+ goto out;
+ }
- /* Separate plans with an appropriate separator */
- if (lnext(l) != NULL)
- ExplainSeparatePlans(&es);
- }
+ /* Explain every plan */
+ foreach(lc, rewritten)
+ {
+ ExplainOneQuery((Query *) lfirst(lc), &es, queryString, params);
+
+ /* Separate plans with an appropriate separator */
+ if (lnext(lc) != NULL)
+ ExplainSeparatePlans(&es);
}
+out:
/* emit closing boilerplate */
ExplainEndOutput(&es);
Assert(es.indent == 0);
@@ -229,6 +253,8 @@ ExplainInitState(ExplainState *es)
/* Set default options. */
memset(es, 0, sizeof(ExplainState));
es->costs = true;
+ es->plan = true;
+ es->rewrite = true;
/* Prepare output buffer. */
es->str = makeStringInfo();
}
diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
index d7998c3..78c4e6d 100644
--- a/src/include/commands/explain.h
+++ b/src/include/commands/explain.h
@@ -31,6 +31,8 @@ typedef struct ExplainState
bool analyze; /* print actual times */
bool costs; /* print costs */
bool buffers; /* print buffer usage */
+ bool plan; /* plan the query */
+ bool rewrite; /* rewrite the query */
ExplainFormat format; /* output format */
/* other states */
PlannedStmt *pstmt; /* top of plan */
--
1.7.7.3