diff options
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r-- | src/backend/commands/explain.c | 96 |
1 files changed, 68 insertions, 28 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 608ebf93ce8..39e8073f55b 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994-5, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.163 2007/05/04 21:29:52 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.164 2007/05/25 17:54:24 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -33,6 +33,12 @@ #include "utils/tuplesort.h" +/* Hook for plugins to get control in ExplainOneQuery() */ +ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL; +/* Hook for plugins to get control in explain_get_index_name() */ +explain_get_index_name_hook_type explain_get_index_name_hook = NULL; + + typedef struct ExplainState { /* options */ @@ -61,6 +67,8 @@ static void show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols, StringInfo str, int indent, ExplainState *es); static void show_sort_info(SortState *sortstate, StringInfo str, int indent, ExplainState *es); +static const char *explain_get_index_name(Oid indexId); + /* * ExplainQuery - @@ -140,9 +148,6 @@ static void ExplainOneQuery(Query *query, ExplainStmt *stmt, const char *queryString, ParamListInfo params, TupOutputState *tstate) { - PlannedStmt *plan; - QueryDesc *queryDesc; - /* planner will not cope with utility statements */ if (query->commandType == CMD_UTILITY) { @@ -151,25 +156,19 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, const char *queryString, return; } - /* plan the query */ - plan = planner(query, 0, params); - - /* - * Update snapshot command ID to ensure this query sees results of any - * previously executed queries. (It's a bit cheesy to modify - * ActiveSnapshot without making a copy, but for the limited ways in which - * EXPLAIN can be invoked, I think it's OK, because the active snapshot - * shouldn't be shared with anything else anyway.) - */ - ActiveSnapshot->curcid = GetCurrentCommandId(); + /* if an advisor plugin is present, let it manage things */ + if (ExplainOneQuery_hook) + (*ExplainOneQuery_hook) (query, stmt, queryString, params, tstate); + else + { + PlannedStmt *plan; - /* Create a QueryDesc requesting no output */ - queryDesc = CreateQueryDesc(plan, - ActiveSnapshot, InvalidSnapshot, - None_Receiver, params, - stmt->analyze); + /* plan the query */ + plan = planner(query, 0, params); - ExplainOnePlan(queryDesc, stmt, tstate); + /* run it (if needed) and produce output */ + ExplainOnePlan(plan, params, stmt, tstate); + } } /* @@ -210,20 +209,35 @@ ExplainOneUtility(Node *utilityStmt, ExplainStmt *stmt, * not running the query. No cursor will be created, however. * * This is exported because it's called back from prepare.c in the - * EXPLAIN EXECUTE case - * - * Note: the passed-in QueryDesc is freed when we're done with it + * EXPLAIN EXECUTE case, and because an index advisor plugin would need + * to call it. */ void -ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt, - TupOutputState *tstate) +ExplainOnePlan(PlannedStmt *plannedstmt, ParamListInfo params, + ExplainStmt *stmt, TupOutputState *tstate) { + QueryDesc *queryDesc; instr_time starttime; double totaltime = 0; ExplainState *es; StringInfoData buf; int eflags; + /* + * Update snapshot command ID to ensure this query sees results of any + * previously executed queries. (It's a bit cheesy to modify + * ActiveSnapshot without making a copy, but for the limited ways in which + * EXPLAIN can be invoked, I think it's OK, because the active snapshot + * shouldn't be shared with anything else anyway.) + */ + ActiveSnapshot->curcid = GetCurrentCommandId(); + + /* Create a QueryDesc requesting no output */ + queryDesc = CreateQueryDesc(plannedstmt, + ActiveSnapshot, InvalidSnapshot, + None_Receiver, params, + stmt->analyze); + INSTR_TIME_SET_CURRENT(starttime); /* If analyzing, we need to cope with queued triggers */ @@ -592,7 +606,7 @@ explain_outNode(StringInfo str, if (ScanDirectionIsBackward(((IndexScan *) plan)->indexorderdir)) appendStringInfoString(str, " Backward"); appendStringInfo(str, " using %s", - quote_identifier(get_rel_name(((IndexScan *) plan)->indexid))); + explain_get_index_name(((IndexScan *) plan)->indexid)); /* FALL THRU */ case T_SeqScan: case T_BitmapHeapScan: @@ -618,7 +632,7 @@ explain_outNode(StringInfo str, break; case T_BitmapIndexScan: appendStringInfo(str, " on %s", - quote_identifier(get_rel_name(((BitmapIndexScan *) plan)->indexid))); + explain_get_index_name(((BitmapIndexScan *) plan)->indexid)); break; case T_SubqueryScan: if (((Scan *) plan)->scanrelid > 0) @@ -1150,3 +1164,29 @@ show_sort_info(SortState *sortstate, pfree(sortinfo); } } + +/* + * Fetch the name of an index in an EXPLAIN + * + * We allow plugins to get control here so that plans involving hypothetical + * indexes can be explained. + */ +static const char * +explain_get_index_name(Oid indexId) +{ + const char *result; + + if (explain_get_index_name_hook) + result = (*explain_get_index_name_hook) (indexId); + else + result = NULL; + if (result == NULL) + { + /* default behavior: look in the catalogs and quote it */ + result = get_rel_name(indexId); + if (result == NULL) + elog(ERROR, "cache lookup failed for index %u", indexId); + result = quote_identifier(result); + } + return result; +} |