3491 Gleb Shchepa 2011-11-14
WL #5855: Print EXPLAIN in JSON format
* normalization of the intermediate JSON tree node structure
+ preprocessor macros for JSON key names
modified:
sql/opt_explain_json.cc
3490 Gleb Shchepa 2011-11-12
Bugfix: a WHERE subquery may be pushed down to more than one JOIN_TABs
modified:
mysql-test/include/explain_json.inc
mysql-test/r/explain_json_all.result
mysql-test/r/explain_json_none.result
sql/item_subselect.cc
sql/opt_explain.cc
sql/opt_explain_format.h
sql/opt_explain_json.cc
sql/opt_explain_json.h
sql/opt_explain_traditional.h
sql/sql_lex.h
sql/sql_union.cc
=== modified file 'sql/opt_explain_json.cc'
--- a/sql/opt_explain_json.cc 2011-11-12 19:48:29 +0000
+++ b/sql/opt_explain_json.cc 2011-11-14 09:20:34 +0000
@@ -16,16 +16,43 @@
#include "opt_trace.h"
#include "opt_explain_json.h"
-#define K_JOIN "join"
-#define K_TABLE "table"
-#define K_SUBQUERY "subquery"
-#define K_DERIVED_SUBQUERY "derived_subquery"
-#define K_WHERE_SUBQUERY "where_subquery"
-#define K_HAVING_SUBQUERY "having_subquery"
-#define K_ORDER_BY_SUBQUERY "order_by_subquery"
-#define K_GROUP_BY_SUBQUERY "group_by_subquery"
-#define K_UNION_RESULT "union_result"
-#define K_QUERY_SPECIFICATION "query_specification"
+// JSON key names
+#define K_ACCESS_TYPE "access_type"
+#define K_CACHEABLE "cacheable"
+#define K_DEPENDENT "dependent"
+#define K_DERIVED_SUBQUERY "derived_subquery"
+#define K_EXTRA "extra"
+#define K_FILTERED "filtered"
+#define K_GROUP_BY_SUBQUERIES "group_by_subqueries"
+#define K_GROUP_BY_SUBQUERY "group_by_subquery"
+#define K_HAVING_SUBQUERIES "having_subqueries"
+#define K_HAVING_SUBQUERY "having_subquery"
+#define K_ID "id"
+#define K_JOIN "join"
+#define K_KEY "key"
+#define K_KEY_LENGTH "key_length"
+#define K_MATERIALIZATION "materialization"
+#define K_MATERIALIZE "materialize"
+#define K_NESTED_LOOPS "nested_loops"
+#define K_OPTIMIZATION_TIME_SUBQUERIES "optimization_time_subqueries"
+#define K_ORDER_BY_SUBQUERIES "order_by_subqueries"
+#define K_ORDER_BY_SUBQUERY "order_by_subquery"
+#define K_PARTITIONS "partitions"
+#define K_POSSIBLE_KEYS "possible_keys"
+#define K_QUERY_SPECIFICATION "query_specification"
+#define K_QUERY_SPECIFICATIONS "query_specifications"
+#define K_REF "ref"
+#define K_ROWS "rows"
+#define K_SELECT_LIST_SUBQUERIES "select_list_subqueries"
+#define K_SELECT_TYPE "select_type"
+#define K_SUBQUERY "subquery"
+#define K_TABLE_NAME "table_name"
+#define K_TABLE "table"
+#define K_UNION_RESULT "union_result"
+#define K_UNION "union"
+#define K_UPDATE_VALUE_SUBQUERIES "update_value_subqueries"
+#define K_WHERE_SUBQUERIES "where_subqueries"
+#define K_WHERE_SUBQUERY "where_subquery"
#define NAMESPACE opt_explain_json_cc
@@ -34,6 +61,7 @@ namespace NAMESPACE { // see commentary
struct joinable_ctx_t;
struct subquery_ctx_t;
+struct union_result_ctx_t;
/**
@note Keep in sync with the @c list_names array.
@@ -55,12 +83,12 @@ enum subquery_list_enum
*/
static const char *list_names[SQ_total]=
{
- "select_list_subqueries",
- "update_value_subqueries",
- "having_subqueries",
- "order_by_subqueries",
- "group_by_subqueries",
- "optimization_time_subqueries"
+ K_SELECT_LIST_SUBQUERIES,
+ K_UPDATE_VALUE_SUBQUERIES,
+ K_HAVING_SUBQUERIES,
+ K_ORDER_BY_SUBQUERIES,
+ K_GROUP_BY_SUBQUERIES,
+ K_OPTIMIZATION_TIME_SUBQUERIES
};
} // namespace
@@ -130,7 +158,7 @@ struct Explain_format_JSON::ctx_t : publ
virtual void set_child(ctx_t *child) {}
/// associate CTX_UNION_RESULT node with CTX_UNION node
- virtual void set_union_result(ctx_t *ctx) { DBUG_ASSERT(0); }
+ virtual void set_union_result(union_result_ctx_t *ctx) { DBUG_ASSERT(0); }
/**
Append a subquery node to the specified list of the unit node
@@ -192,8 +220,13 @@ struct Explain_format_JSON::ctx_t : publ
return false;
}
+ /// Helper function to format output for derived subquery if any
virtual bool format_derived(Opt_trace_context *json) { return false; }
+
+ /// Helper function to format output for associated WHERE subqueries if any
virtual bool format_where(Opt_trace_context *json) { return false; }
+
+ /// Helper function to format output for HAVING, ORDER/GROUP BY subqueries
virtual bool format_unit(Opt_trace_context *json) { return false; }
};
@@ -325,7 +358,7 @@ struct table_base_ctx_t : virtual public
StringBuffer<64> buff;
if (!col_id.is_empty())
- obj->add("id", col_id.value);
+ obj->add(K_ID, col_id.value);
if (!col_select_type.is_empty())
{
@@ -333,43 +366,43 @@ struct table_base_ctx_t : virtual public
if (type == SELECT_LEX::SLT_UNION)
type= SELECT_LEX::SLT_PRIMARY;
const char *str= SELECT_LEX::get_type_str(type);
- obj->add_alnum("select_type", str);
+ obj->add_alnum(K_SELECT_TYPE, str);
if (is_dependent)
- obj->add("dependent", is_dependent);
+ obj->add(K_DEPENDENT, is_dependent);
if (!is_cacheable)
- obj->add("cacheable", is_cacheable);
+ obj->add(K_CACHEABLE, is_cacheable);
}
if (!col_table_name.is_empty())
- obj->add_utf8("table_name", col_table_name.str);
+ obj->add_utf8(K_TABLE_NAME, col_table_name.str);
if (!col_partitions.is_empty())
- obj->add_utf8("partitions", col_partitions.str);
+ obj->add_utf8(K_PARTITIONS, col_partitions.str);
if (!col_join_type.is_empty())
- obj->add_alnum("access_type", col_join_type.str);
+ obj->add_alnum(K_ACCESS_TYPE, col_join_type.str);
if (!col_possible_keys.is_empty())
- obj->add_utf8("possible_keys", col_possible_keys.str);
+ obj->add_utf8(K_POSSIBLE_KEYS, col_possible_keys.str);
if (!col_key.is_empty())
- obj->add_utf8("key", col_key.str);
+ obj->add_utf8(K_KEY, col_key.str);
if (!col_key_len.is_empty())
- obj->add_alnum("key_length", col_key_len.str);
+ obj->add_alnum(K_KEY_LENGTH, col_key_len.str);
if (!col_ref.is_empty())
- obj->add_utf8("ref", col_ref.str);
+ obj->add_utf8(K_REF, col_ref.str);
if (!col_rows.is_empty())
- obj->add("rows", col_rows.value);
+ obj->add(K_ROWS, col_rows.value);
if (!col_filtered.is_empty())
- obj->add("filtered", col_filtered.value);
+ obj->add(K_FILTERED, col_filtered.value);
if (!col_extra.is_empty())
{
- Opt_trace_array extra(json, "extra");
+ Opt_trace_array extra(json, K_EXTRA);
List_iterator<const char> it(col_extra);
const char *s;
@@ -387,33 +420,58 @@ struct table_base_ctx_t : virtual public
/**
- Node class for the CTX_TABLE and CTX_UNION_RESULT
+ Node class for the CTX_UNION_RESULT
*/
+struct union_result_ctx_t : public table_base_ctx_t, public unit_ctx_t
+{
+ explicit union_result_ctx_t(ctx_t *parent_arg)
+ : ctx_t(CTX_UNION_RESULT, "union_result", parent_arg),
+ table_base_ctx_t(CTX_UNION_RESULT, "union_result", parent_arg),
+ unit_ctx_t(CTX_UNION_RESULT, "union_result", parent_arg)
+ {}
+};
+
+
+/**
+ Common part of CTX_TABLE, CTX_JOIN_TAB and CTX_MESSAGE nodes
-struct table_ctx_t : public table_base_ctx_t, public unit_ctx_t
+ This class implements functionality for WHERE and derived subqueries that
+ are associated with the table node.
+*/
+struct table_with_where_and_derived_t : public table_base_ctx_t
{
List<subquery_ctx_t> where_subqueries; ///< associated WHERE clause subqueries
- table_ctx_t(Explain_context_enum type_arg,
- const char *name_arg, ctx_t *parent_arg)
+ table_with_where_and_derived_t(Explain_context_enum type_arg,
+ const char *name_arg, ctx_t *parent_arg)
: ctx_t(type_arg, name_arg, parent_arg),
- table_base_ctx_t(type_arg, name_arg, parent_arg),
- unit_ctx_t(type_arg, name_arg, parent_arg)
+ table_base_ctx_t(type_arg, name_arg, parent_arg)
{}
- virtual bool format_derived(Opt_trace_context *json)
- {
- DBUG_ASSERT(derived_select_number == 0 || derived_from != NULL);
- return derived_from && static_cast<ctx_t *>(derived_from)->format(json);
- }
-
virtual bool format_where(Opt_trace_context *json)
{
return (!where_subqueries.is_empty() &&
format_list(json, where_subqueries, "where_subqueries"));
}
+ virtual void register_where_subquery(SELECT_LEX_UNIT *)
+ {
+ // Empty
+ }
+
+ virtual bool add_where_subquery(subquery_ctx_t *ctx,
+ SELECT_LEX_UNIT *subquery)
+ {
+ return where_subqueries.push_back(ctx);
+ }
+
+ virtual bool format_derived(Opt_trace_context *json)
+ {
+ DBUG_ASSERT(derived_select_number == 0 || derived_from != NULL);
+ return derived_from && static_cast<ctx_t *>(derived_from)->format(json);
+ }
+
virtual bool find_and_set_derived(ctx_t *subquery)
{
if (derived_select_number == subquery->id())
@@ -424,17 +482,21 @@ struct table_ctx_t : public table_base_c
}
return false;
}
+};
- virtual void register_where_subquery(SELECT_LEX_UNIT *)
- {
- // Empty
- }
- virtual bool add_where_subquery(subquery_ctx_t *ctx,
- SELECT_LEX_UNIT *subquery)
- {
- return where_subqueries.push_back(ctx);
- }
+/**
+ Node class for the CTX_TABLE
+*/
+struct table_ctx_t : public table_with_where_and_derived_t,
+ public unit_ctx_t
+{
+ table_ctx_t(Explain_context_enum type_arg,
+ const char *name_arg, ctx_t *parent_arg)
+ : ctx_t(type_arg, name_arg, parent_arg),
+ table_with_where_and_derived_t(type_arg, name_arg, parent_arg),
+ unit_ctx_t(type_arg, name_arg, parent_arg)
+ {}
};
@@ -454,6 +516,12 @@ struct message_ctx_t : virtual public ta
};
+/**
+ Base class for CTX_JOIN_TAB and CTX_MATERIALIZATION nodes
+
+ This class implements a base to explain individual JOIN_TABs as well
+ as JOIN_TAB groups like in semi-join materialization.
+*/
struct joinable_ctx_t : virtual public ctx_t
{
joinable_ctx_t(Explain_context_enum type_arg, const char *name_arg,
@@ -463,7 +531,11 @@ struct joinable_ctx_t : virtual public c
};
-struct join_tab_ctx_t : public joinable_ctx_t, public table_ctx_t
+/**
+ Node class for the CTX_JOIN_TAB context
+*/
+struct join_tab_ctx_t : public joinable_ctx_t,
+ public table_with_where_and_derived_t
{
/**
Subquery units that are associated with this JOIN_TAB's condition
@@ -476,7 +548,7 @@ struct join_tab_ctx_t : public joinable_
join_tab_ctx_t(Explain_context_enum type_arg, ctx_t *parent_arg)
: ctx_t(type_arg, K_TABLE, parent_arg),
joinable_ctx_t(type_arg, K_TABLE, parent_arg),
- table_ctx_t(type_arg, K_TABLE, parent_arg)
+ table_with_where_and_derived_t(type_arg, K_TABLE, parent_arg)
{}
virtual void register_where_subquery(SELECT_LEX_UNIT *subquery)
@@ -631,7 +703,7 @@ struct materialize_ctx_t : public joinab
struct union_ctx_t : public unit_ctx_t
{
- ctx_t *union_result; ///< associated CTX_UNION_RESULT node
+ union_result_ctx_t *union_result; ///< associated CTX_UNION_RESULT node
List<ctx_t> query_specs; ///< query specification nodes (inner selects)
explicit union_ctx_t(ctx_t * parent_arg)
@@ -660,7 +732,7 @@ struct union_ctx_t : public unit_ctx_t
}
virtual size_t id() { return query_specs.head()->id(); }
- virtual void set_union_result(ctx_t *ctx)
+ virtual void set_union_result(union_result_ctx_t *ctx)
{
DBUG_ASSERT(union_result == NULL);
union_result= ctx;
@@ -796,8 +868,7 @@ bool Explain_format_JSON::begin_context(
case CTX_UNION_RESULT:
{
DBUG_ASSERT(current_context->type == CTX_UNION);
- table_ctx_t *ctx= new table_ctx_t(CTX_UNION_RESULT, K_UNION_RESULT,
- current_context);
+ union_result_ctx_t *ctx= new union_result_ctx_t(current_context);
if (ctx == NULL)
return true;
current_context->set_union_result(ctx);
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (gleb.shchepa:3490 to 3491) WL#5855 | Gleb Shchepa | 14 Nov |