List:Commits« Previous MessageNext Message »
From:Gleb Shchepa Date:November 14 2011 9:22am
Subject:bzr push into mysql-trunk branch (gleb.shchepa:3490 to 3491) WL#5855
View as plain text  
 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#5855Gleb Shchepa14 Nov